从给定的字符串数组中查找所有子字符串的算法

时间:2016-04-15 09:10:09

标签: string algorithm array-algorithms string-algorithm

我需要从给定的字符串数组中找到所有子字符串并对它们进行分组。

附加条件:

如果字符串S1包含字符串S2,S1包含S3,则S2包含S4 - 它们应该在一个组中。

示例:

给定数组: 你好,你好约翰,嗨,嗨鲍勃,地狱,大家好

结果输出:

第1组:你好,你好约翰,地狱

第2组:嗨,嗨鲍勃,大家好

1 个答案:

答案 0 :(得分:1)

  • 在字符串数组
  • 上构建trie
  • 对于每个数组条目,遍历trie,如果当前节点标记一个单词,则打印它(与当前字符串在同一组下)。做一些簿记,以避免多次打印相同的单词。

构建轮胎的时间复杂度为O(|w1| + ... + |wn|),其中|wi|是字符串wi的长度;所以它在弦长的总和上是线性的。空间复杂性受到相同表达式的限制,但是当存在许多共同前缀时(实际上会发生这种情况),空间复杂度要低得多。

查询步骤的时间复杂度在字符串的长度上是线性的 - 只是遍历与字符串对应的分支。 (也许你可以标记你在途中访问过的字符串---并因此以当前字符串为前缀 - 以便你以后甚至不会遍历它们。访问更长的字符串会帮助你带来时间复杂性进一步下来。)

这是一个让你入门的结构:

typedef struct node_t_ node_t;
struct node_t_ {
    node_t c *children[ALPHABET_SIZE];
    char kIsLeaf; // set to 1 if represents a word
    char ch; // character stored in the leaf (redundant)
}

插入很简单。您从非NULL root开始,它存储零字符(表示空字符串)。

插入:

 void insert(const char* str) {
    node_t* current = root;
    while (*str != '\0') {
        if (current->children[*str] == NULL) {
            create new node;
        }
        current = current->children[*str++];
    }
    current->kIsLeaf = 1;
}

其他程序非常相似。 Trie是一个非常优雅,易于实现且易于使用的数据结构。