在字典中查找String的最长子序列

时间:2016-10-20 15:41:21

标签: algorithm subsequence

查找字符串中最长的子序列,例如“abccdde” 给了一个字典{“ab”,“add”,“aced”} 。上面例子的结果是“添加”

我在接受采访时被问到,我用树木给出答案,最坏的情况是O(n * m) ,n是s的长度 ,m是字典的长度。 但我的平均成本应该很低。我没有通过面试,因为面试官认为我的解决方案并不是最好的。有没有人有更好的主意?

5 个答案:

答案 0 :(得分:1)

您可以创建图形,然后顶点就是您的字母。对于词典中的每个单词,您可以在图表中添加第一个字符:

G[word[0]].add({word, 0})

然后,当您访问每封信的文字时,您会访问该信件的adyacency列表。对于列表中的每个项目,您应该为该单词添加下一个字符。

用你的例子:

S = "abccdde", D = {"ab","add","aced"}

第一步:

G = {{'a', [{"ab", 0}, {"add", 0}, {"aced", 0}]}}

对于S

中的每个字符
  • character =' a' - > S [0]

您访问该角色的列表

[{"ab", 0}, {"add", 0}, {"aced", 0}]

并更新您的图表

G = {{'b', [{"ab", 1}]}, {'d', ["add", 1]}, {'c', [{"aced", 1}]}}
  • 字符' b' - > S [1]

您访问该角色的列表

[{"ab", 1}]

并更新您的图表

G = {{'d', ["add", 1]}, {'c', [{"aced", 1}]}}

当你完成" ab"你可以尝试改善你的答案。

  • 字符' c' - > S [2]

您访问该角色的列表

[{"aced", 1}]

并更新您的图表

G = {{'d', ["add", 1]}, {'e', [{"aced", 2}]}}
  • 字符' c' - > S [3]

没有该字符的列表,然后您继续使用下一个字符

  • 字符' d' - > S [4]

您访问该角色的列表

["add", 1]

并更新您的图表

G = {{'d', ["add", 2]}, {'e', [{"aced", 2}]}}

...

答案 1 :(得分:0)

您可以使用此方法

public static Boolean IsSubsequence(string ch, string item)
{
    if (ch.Length < item.Length)
    {
        return false;
    }
    int indexItem = 0;
    int indexCh = 0;
    while (indexCh < ch.Length && indexItem< item.Length)
    {
        if (ch[indexCh] == item[indexItem])
        {
            indexItem++;
        }
        indexCh++;
    }
    return indexItem == item.Length;
}

是o(n)方法 您也可以通过单词lenght对字典项进行排序,这样第一个返回true的结果就是结果

答案 2 :(得分:0)

安排你的字典数据结构,使每个有效字母更深入树中(查看一个字母更长的单词),并添加一个默认情况(没有带此前缀的匹配字母),指向最长的有效前缀比当前深度短(还有一个标志,表示你已经有一个单词,以防万一这是你最好的选择)。

如果您错过了'asparag'后跟'r',您的字典会将您引导至'sparag'的树 iff 有任何此类单词,如果没有,则指示您'parag'。

对于每次失败,如果仍然没有匹配,则重复测试并递归到较短的单词;所以这仍然比O(n)更糟糕......虽然一个随意思考的时刻表明最坏的情况可能是O(2n)。

为了加快速度,默认情况下可以是默认的列表,您可以从中选择与当前字母匹配的条目。所有条目将至少匹配一个长度为0的条目(当前字母不开始单词)或1(仅当前字母)。

答案 3 :(得分:0)

这是我的Python代码,用于时间复杂度为O(N + L)的解决方案,其中N是字符串中的字符数(N = 7表示&#34; abccdde&#34;),L是字典中的总字符数(对于{&#34; ab&#34;,&#34;添加&#34;,&#34; aced&#34;},L = 9)。基本上,它是线性时间复杂度。

def find_longest_word_in_string(string, words):
    m = {}

    for word in words:
        m[word] = 0

    for c in string:
        for word in m.keys():
            if len(word) == m[word]:
                continue
            else:
                if word[m[word]] == c:
                    m[word] += 1

    length = 0
    for word in m.keys():
        if m[word] == len(word) and m[word] > length:
            res = word
            length = m[word]

    return res

if __name__ == '__main__':
   s = "abccdde"                 
   words = ["ab","add","aced"]    
   print find_longest_word_in_string(s, words)

运行它,返回&#39;添加&#39;

答案 4 :(得分:0)

我认为不可能只使用一个循环来减少算法可以花费的时间,至少它需要两个循环我想,这是我的方法:

public String lookFor(String inputWord, String[] dictionary) {

  Arrays.sort(dictionary);

  for (int index = dictionary.length - 1; index > 0; index--) {
    if (isTheWordASubsequence(inputWord, dictionary[index]))
      return dictionary[index];
  }

  return null;
}

private boolean isTheWordASubsequence(String inputWord,
    String dictionaryWord) {

  int spot = 0;
  int offset = 0;

  for (char item : dictionaryWord.toCharArray()) {
    spot = (offset = inputWord.indexOf(item, spot)) >= spot ? offset : -1;
    if (spot < 0)
      return false;
  }

  return true;
}