【问题标题】:Find the longest word in the array consisting of other words in the array查找由数组中其他单词组成的数组中最长的单词
【发布时间】:2015-05-04 10:12:50
【问题描述】:

我有一个单词数组,需要找到数组中最长的单词,该单词由该数组中的其他单词组成。例如:

  String[] mass = {
            "five",
            "fivetwo",
            "fourfive",
            "fourfivetwo",
            "one",
            "onefiveone",
            "two",
            "twofivefourone"
        };

结果应该是 "fourfivetwo" -> "fourfive" "two"。你能帮我找到算法吗?

【问题讨论】:

  • 请重新提出问题。输出和问题没有关联。
  • 我没有看到任何代码,甚至没有解决这个问题的想法。基本上很简单:在数组中找到所有最小的单词,比如 "one" 、 "two" 等......并将它们用作您的字母表。将所有单词翻译成字母表字符串并搜索最长的结果字符串。
  • 你到底想表达什么?
  • 这不是免费的代码工厂。如果您确实展示了解决问题的努力,而不是仅仅描述您希望别人为您写的内容,您将更有可能获得帮助。
  • 如果您询问“用您最喜欢的编程语言执行此操作的最短程序是什么”之类的问题,您可能有机会联系codegolf.stackexchange.com! :-) 很有可能有人用 C 语言写了一个单行字——但你需要两页散文来向你的老师解释这个程序。

标签: arrays algorithm find


【解决方案1】:

存在使用字符串匹配算法 KMP 和图形的解决方案。

算法:

1) 迭代单词。为“主要词”设置每个词,即您要构建的词。对每个这样的单词执行以下步骤。

2) 您修复了一个单词,我们称之为 W。现在再次遍历所有单词并运行 KPM 将它们与 W 进行比较。现在您可以根据单词 W 的字母构建图表。让我们举例说明:

W = "abacdeeee"
Other_word = ["aba", "cde", "eee"]

Word "aba" would connect letter 1 in word W to letter 4.
Word "cde" would connect 4 to 7.
Word "eee" would connect 7 to 9.

Each letter in W is node and other words will make edges. 
If there exists a path between first and last letter, which you can 
check using BFS/DFS, you can build word W out of other words.

3) 对每个单词重复该过程并选择可以从其他单词中构建的最长的单词。

时间复杂度:

假设 N 是单词数,L 是平均长度。

对于单个单词,您可以将 KMP 与其他单词一起运行,这需要 O(N * (L + L))。在最坏的情况下,构建图需要 O(N^2),对于 BFS 也是如此。对于每个单词 W,您在最坏的情况下花费 O(NL + N^2),但边数很可能与 N 成正比,因此平均值为 O(NL)。

因为你需要对每个 N 进行上述操作,你会得到结果:

最差复杂度:O(N^2*L + N^3)

平均复杂度:O(N^2*L)

【讨论】:

  • 1.我认为你对 O(N^2*L) 的结论是正确的,但是写“对于每个单词,你对每个单词运行 KPM,这将需要 O(N*(L+L))”会让人困惑。我建议将第一个“每个”更改为“单个”,将第二个“每个”更改为“彼此”。 2. Aho-Corasick 算法提供了比运行 N 次 KMP 更快的方法。 3. 你不需要构建一个通用的 O(N^2) 大小的图——你可以“交错”单独的 KMP 运行,然后你只需要记录,对于每个字符串位置,该位置是否可以从位置 1(O(L) 空间和时间)。 4. 我一直看到它拼写为“KMP”。
  • 感谢您的留言。我同意你的观点。相应地进行了编辑。
【解决方案2】:

谢谢大家,我已经决定了,如果有人有兴趣这里的代码。我为它感到羞耻,但它有效

public class MyMap {

private Map<String, ArrayList<Pair>> map = new TreeMap<String, ArrayList<Pair>>();
private String[] key;
// create special map
//key = element our array
//value = pair elemene 
//              string = word which contains in this key
//              int = count this word (which contains in this key)

public MyMap(String[] ArrayWord) {
    key = ArrayWord;
    //init arraylist
    for (int i = 0; i < ArrayWord.length; i++) {
        map.put(ArrayWord[i], new ArrayList<Pair>());
    }
    //find word which containing key
    /*
     example:
     String[] mass = {
     "f",
     "five",
     "fivetwo",
     "one",
     "onefiveone",
     "two"
     };
     map[0] => f->[]
     map[1] => five->[(f:1)]
     map[2] => fivetwo->[(f:1)(five:1)(two:1)]
     map[3] => one->[]
     map[4] => onefiveone->[(f:1)(five:1)(one:2)]
     map[5] => two->[]*/
    for (int i = 0; i < ArrayWord.length; i++) {
        for (int j = 0; j < ArrayWord.length; j++) {
            if (i != j) {
                int count = 0;
                if (ArrayWord[i].contains(ArrayWord[j])) {
                    String str = ArrayWord[i];
                    // find count word which contains in this key
                    while (str.contains(ArrayWord[j])) {
                        str = str.replaceFirst(ArrayWord[j], "-");
                        count++;
                    }
                    Pair help = new Pair(ArrayWord[j], count);
                    map.get(ArrayWord[i]).add(help);
                }

            }
        }
    }
}

public String getCompoundWord() {
    String word = "";
    //check have we compound word or not 
    if (isHaveCompoundWords()) {
        /*remove Unique Elements of the words are found*/
        deleteContainingWord();
        /* find index element*/
        int index = findIndexCompoundWord();
        //return -1 if we have no word which compound just with other words array
        try {
            word = key[findIndexCompoundWord()];
            return word;
        } catch (IndexOutOfBoundsException ex) {
            System.out.println("Have no word which compound just with other words array");
        }
    } else {
        return "Have no word which compound with other words array, just unique element";
    }

    return key[findIndexCompoundWord()];
}

private void deleteContainingWord() {
    /*
     update map
     after procedure we would have map like this           
     String[] mass = {
     "f",
     "five",
     "fivetwo",
     "one",
     "onefiveone",
     "two"
     };
     map[0] => f->[]
     map[1] => five->[(f:1)]
     map[2] => fivetwo->[(f:1)(ive:1)(two:1)]
     map[3] => one->[]
     map[4] => onefiveone->[(f:1)(ive:1)(one:2)]
     map[5] => two->[]
     */
    for (int i = 0; i < map.size(); i++) {
        if (map.get(key[i]).size() > 0) {
            ArrayList<Pair> tmp = map.get(key[i]);
            for (int j = tmp.size() - 1; j >= 0; j--) {
                for (int k = tmp.size() - 1; k >= 0; k--) {
                    if (k != j) {
                        // if word contains other word2, remove part word
                        if (tmp.get(j).getName().contains(tmp.get(k).getName())) {
                            String s = tmp.get(j).getName().replace(tmp.get(k).getName(), "");
                            tmp.get(j).setName(s);
                        }
                    }
                }
            }
            map.put(key[i], tmp);
        }
    }
}

private int findIndexCompoundWord() {
    int indexMaxCompaneWord = -1;
    int maxCompaneWordLenght = 0;
    for (int i = 0; i < map.size(); i++) {
        if (map.get(key[i]).size() > 0) {
            ArrayList<Pair> tmp = map.get(key[i]);
            int currentWordLenght = 0;
            for (int j = 0; j < tmp.size(); j++) {
                if (!tmp.get(j).getName().isEmpty()) {
                    currentWordLenght += tmp.get(j).getName().length() * tmp.get(j).getCount();
                }
            }
            if (currentWordLenght == key[i].length()) {
                if (maxCompaneWordLenght < currentWordLenght) {
                    maxCompaneWordLenght = currentWordLenght;
                    indexMaxCompaneWord = i;
                }
            }
        }
    }
    return indexMaxCompaneWord;
}

private boolean isHaveCompoundWords() {
    boolean isHaveCompoundWords = false;
    for (int i = 0; i < map.size(); i++) {
        if (map.get(key[i]).size() > 0) {
            isHaveCompoundWords = true;
            break;
        }
    }
    return isHaveCompoundWords;
}

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-09
    • 2018-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-07
    相关资源
    最近更新 更多