[leetcode]472. Concatenated Words

题目链接:https://leetcode.com/problems/concatenated-words/description/

 

Given a list of words (without duplicates), please write a program that returns all 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:

Input: ["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".

 

Note:

  1. The number of elements of the given array will not exceed 10,000
  2. The length sum of elements in the given array will not exceed 600,000.
  3. All the input string will only include lower case letters.
  4. The returned elements order does not matter.

 

class Solution {
public:
    vector<string> findAllConcatenatedWordsInADict(vector<string>& words) {
		vector<string> res;
		unordered_set<string> s(words.begin(), words.end());
		for(auto w: words) {
			vector<bool> dp(w.size() + 1, false);
			dp[0] =  true;

			for(int i = 1; i <= w.size(); i++) {
				for(int j = i - 1; j >= 0; j--) {
					string t = w.substr(j, i - j);
					if(i - j < w.size() && s.count(t) && dp[j]) {
						dp[i] = true;
					}
				}

			if(i == w.size() && dp[i])
				res.push_back(w);
			}
			
		}

		return res;
	}
};

 

方法一:(dp)

For any qualified word, there must be at least 3 indexes (at least 1 besides 0 and n-1 which n is the length of the word), which can be used to split the whole string to at least two sub strings and all sub strings can be found in words.
E.g. input ["cat","cats", "dog", "sdog","dogcatsdog"], for word dogcatsdog, there are 2 sets of numbers: [0, 3, 6, 10] and [0, 3, 7, 10] which can be formed by concatenating [dog, cat, sdog] and [dog, cats, dog] respectively.
So, we can use a vector<int> dp(n+1) to store if w.substr(0, i) can be formed by existing words. Once i reach to n and it is not the word itself, we put the word to results.

 

 

 

 

 

class Solution {
public:
    vector<string> findAllConcatenatedWordsInADict(vector<string>& words) {
        vector<string> res;
        unordered_set<string> s(words.begin(),words.end());
        for(auto w:words)
        {
            int n=w.size();
            vector<int> dp(n+1);
            dp[0]=1;
            for(int i=0;i<n;i++){
                if(dp[i]==0) continue;
                for(int j=i+1;j<=n;j++)
                {
                    if(j-i<n && s.count(w.substr(i,j-i))) dp[j]=1;
                }
                if(dp[n])
                {
                    res.push_back(w);
                    break;
                }
            }
        }
        return res;
    }
};

 

 

 

 

 

方法二:(dfs)

 

class Solution {
public:
    vector<string> findAllConcatenatedWordsInADict(vector<string>& words) {
        vector<string> res;
        sort(words.begin(),words.end(),[](const string &lhs,const string rhs){return lhs.length()<rhs.length();});
        for(auto &word:words)
        {
            if(dfs(word,0))
                res.push_back(word);
            else
                dict.insert(word);
        }
        return res;
    }
private:
    unordered_set<string> dict;
    bool dfs(string word,int count)
    {
        if(word.empty())
            return count>1;
        int n=word.length();
        for(int i=1;i<=n;i++)
        {
            if(dict.count(word.substr(0,i)) && dfs(word.substr(i),count+1))
                return true;
        }
        return false;
    }
};


方法三:(Trie Tree MLE)

 

 

class TrieNode{
public:
    TrieNode* next[26];
    bool isword;
    TrieNode():isword(false)
    {
        memset(next,0,sizeof(next));
    }
};


class Trie{
public:
    Trie(){
        root=new TrieNode();
    }

    void insert(string word){
        TrieNode*p =root;
        for(int i=0;i<word.size();i++)
        {
            if(p->next[word[i]-'a']==NULL)
                p->next[word[i]-'a']=new TrieNode();
            p=p->next[word[i]-'a'];
        }
        p->isword=true;
    }

    //从末端进行搜索,能够优化一些效率
    vector<int> search(string word)
    {
        vector<int> res;
        TrieNode* p=root;
        for(int i=0;i<word.size();i++)
        {
            if(p->isword)
                res.push_back(i);
            if(p->next[word[i]-'a']==NULL)
                return res;
            p=p->next[word[i]-'a'];
        }

        return res;
    }

private:
    TrieNode* root;
};

class Solution {
public:
    vector<string> findAllConcatenatedWordsInADict(vector<string>& words) {
        sort(words.begin(),words.end(),cmp);

        vector<string> res;
        for(auto &word:words)
        {
            if(word.empty())
                continue;
            if(judge(word,0))
                res.push_back(word);
            trie.insert(word);
            mark[word]=1;
        }
        return res;
    }
private:
    Trie trie;
    unordered_map<string,int> mark;
    static bool cmp(const string &a,const string &b){
        return a.size()<b.size();
    };
    //k这个主要用来记录是否是最外层的,如果不是最外层的话,则只需要喊str这个串本身是否含在已包含的字符串中就好。
    bool judge(string& str,int k)
    {
        vector<int> res=trie.search(str);
        //从末端进行搜索,能够优化一些效率
        reverse(res.begin(),res.end());
        if(k==1)
        {
            if(mark.find(str)!=mark.end())
                return true;
        }
        for(int i=0;i<res.size();i++)
        {
            string tmp=str.substr(res[i]);
            if(judge(tmp,1))
            {
                mark[str]=1;
                return true;
            }
        }
        return false;
    }
};


方法四:(暴力破解)

 

 

class Solution {
public:
    vector<string> findAllConcatenatedWordsInADict(vector<string>& words) {
        sort(words.begin(),words.end(),cmp);
        vector<string> res;
        for(auto & word:words)
        {
            if(word.size()==0)
                continue;
            if(judge(word,0,""))
                res.push_back(word);
            mark.insert(word);
        }
        return res;
    }
private:
    unordered_set<string> mark;
    static bool cmp(const string &a,const string &b)
    {
        return a.size()<b.size();
    };
    bool judge(string &word,int pos,string str)
    {
        if(pos==word.size())
        {
            if(mark.find(str)!=mark.end())
                return true;
            return false;
        }
        str+=word[pos];
        if(mark.find(str)!=mark.end())
        {
            string tmp="";
            if(judge(word,pos+1,""))
                return true;
        }
        return judge(word,pos+1,str);
    }
};

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值