LeetCode #472 Concatenated Words 连接词

472 Concatenated Words 连接词

Description:
Given an array of strings words (without duplicates), return all the concatenated words in the given list of words.

A concatenated word is defined as a string that is comprised entirely of at least two shorter words in the given array.

Example:

Example 1:

Input: words = ["cat","cats","catsdogcats","dog","dogcatsdog","hippopotamuses","rat","ratcatdogcat"]
Output: ["catsdogcats","dogcatsdog","ratcatdogcat"]
Explanation: "catsdogcats" can be concatenated by "cats", "dog" and "cats";
"dogcatsdog" can be concatenated by "dog", "cats" and "dog";
"ratcatdogcat" can be concatenated by "rat", "cat", "dog" and "cat".

Example 2:

Input: words = ["cat","dog","catdog"]
Output: ["catdog"]

Constraints:

1 <= words.length <= 10^4
0 <= words[i].length <= 1000
words[i] consists of only lowercase English letters.
0 <= sum(words[i].length) <= 6 * 10^5

题目描述:
给定一个 不含重复 单词的字符串数组 words ,编写一个程序,返回 words 中的所有 连接词 。

连接词 的定义为:一个字符串完全是由至少两个给定数组中的单词组成的。

示例 :

示例 1:

输入:words = ["cat","cats","catsdogcats","dog","dogcatsdog","hippopotamuses","rat","ratcatdogcat"]
输出:["catsdogcats","dogcatsdog","ratcatdogcat"]
解释:"catsdogcats"由"cats", "dog" 和 "cats"组成;
"dogcatsdog"由"dog", "cats"和"dog"组成;
"ratcatdogcat"由"rat", "cat", "dog"和"cat"组成。

示例 2:

输入:words = ["cat","dog","catdog"]
输出:["catdog"]

提示:

1 <= words.length <= 10^4
0 <= words[i].length <= 1000
words[i] 仅由小写字母组成
0 <= sum(words[i].length) <= 6 * 10^5

思路:

前缀树 Trie
先建立每个单词的前缀树
按照字符串的长度进行排序
先搜索短的, 如果搜索到单词结尾, 搜索剩下的字符串是否也在前缀树中
时间复杂度O(nlgn * m ^ 3), 空间复杂度O(n), 其中 n为单词数, m为单词的最长的长度

代码:
C++:

struct Trie
{
    bool word;
    struct Trie* next[26]{nullptr};
};
class Solution 
{
public:
    vector<string> findAllConcatenatedWordsInADict(vector<string>& words) 
    {
        sort(words.begin(), words.end(), [](auto &a, auto &b) { return a.size() < b.size(); });
        vector<string> result;
        for (auto &word: words) 
        {
            if (word.empty()) continue;
            if (search(word)) result.emplace_back(word);
            else insert(word);
        }
        return result;
    }
private:
    Trie* root = new Trie();
    
    bool search(string &word) 
    {
        Trie *cur = root;
        if (word.empty()) return true;
        for (int i = 0, n = word.size(), c; i < n; i++) 
        {
            c = word[i] - 'a';
            string child = word.substr(i + 1);
            if (!cur -> next[c]) return false;
            if (cur -> next[c] -> word) if (search(child)) return true;
            cur = cur -> next[c];
        }
        return false;
    }

    void insert(string &word) 
    {
        Trie *cur = root;
        for (int i = 0, n = word.size(), c; i < n; i++) 
        {
            c = word[i] - 'a';
            if (!cur -> next[c]) cur -> next[c] = new Trie();
            cur = cur -> next[c];
        }
        cur -> word = true;
    }
};

Java:

class Trie {
    public boolean word = false;
    public Trie[] next = new Trie[26];
}

class Solution {
    Trie root = new Trie();
    public List<String> findAllConcatenatedWordsInADict(String[] words) {
        Arrays.sort(words, new Comparator<String>() {
            @Override
            public int compare(String a, String b) {
                return a.length() - b.length();
            } 
        });
        List<String> result = new ArrayList<>();
        for (String word: words) {
            if (word.length() == 0) continue;
            if (search(word)) result.add(word);
            else insert(word);
        }
        return result;
    }

    public boolean search(String word) {
        Trie cur = root;
        int n = word.length();
        if (n == 0) return true;
        for (int i = 0, c; i < n; i++) {
            c = word.charAt(i) - 'a';
            if (cur.next[c] == null) return false;
            if (cur.next[c].word) if (search(word.substring(i + 1))) return true;
            cur = cur.next[c];
        }
        return false;
    }

    public void insert(String word) {
        Trie cur = root;
        for (int i = 0, n = word.length(), c; i < n; i++) {
            c = word.charAt(i) - 'a';
            if (cur.next[c] == null) cur.next[c] = new Trie();
            cur = cur.next[c];
        }
        cur.word = true;
    }
}

Python:

class Solution:
    
    class Trie:
        def __init__(self):
            self.next = [None] * 26
            self.word = False
            
            
    def findAllConcatenatedWordsInADict(self, words: List[str]) -> List[str]:
        words.sort(key=len)
        root = self.Trie()
        result = []
        
        def search(word: str) -> bool:
            if not word:
                return True
            cur, n = root, len(word)
            for i in range(n):
                c = ord(word[i]) - ord('a')
                if not cur.next[c]:
                    return False
                if cur.next[c].word:
                    if search(word[i + 1:]):
                        return True
                cur = cur.next[c]
            return False
        
        def insert(word: str) -> None:
            cur, n = root, len(word)
            for i in range(n):
                c = ord(word[i]) - ord('a')
                if not cur.next[c]:
                    cur.next[c] = self.Trie()
                cur = cur.next[c]
            cur.word = True
            
        for word in words:
            if not word:
                continue
            if search(word):
                result.append(word)
            else:
                insert(word)
        return result
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容