【问题标题】:Algorithm to find all substrings from the given array of string从给定的字符串数组中查找所有子字符串的算法
【发布时间】:2016-04-15 09:10:09
【问题描述】:

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

附加条件:

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

示例:

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

结果输出:

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

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

【问题讨论】:

  • 你在哪里有问题?
  • 在我当前的实现(蛮力)中,我面临着 N*N 复杂性(这是预期的),这不适用于大型数组。

标签: string algorithm array-algorithms string-algorithm


【解决方案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 是一种非常优雅、易于实现且易于使用的数据结构。

【讨论】:

  • 但是对于“Hello world”、“world”等键,我们应该怎么做呢?它们也应该在一个组中,因为第一个字符串包含第二个字符串,但在 Trie 中它们将位于不同的路径中。
  • 如果它在中间,比如“你好”和“嗯,你好!” ?
猜你喜欢
  • 2012-04-20
  • 2023-01-19
  • 2015-07-22
  • 2019-03-29
  • 2016-04-20
  • 1970-01-01
  • 2017-05-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多