【LeetCode 30】串联所有单词的子串

题目链接

【题解】

开个字典树记录下所有的单词。 然后注意题目的已知条件 每个单词的长度都是一样的。 这就说明不会出现某个字符串是另外一个字符串的前缀的情况(除非相同). 所以可以贪心地匹配(遇到什么字符就在字典树里面沿着边从根往下走就好). 假设给的单词的个数为len.(每个单词的长度都是L) 显然从每个位置开始都要匹配len次。而且每次都要匹配L个字符。 然后因为可能会出现一个单词出现多次的情况。 那么你得记录一下之前某个单词用了多少次。

【代码】

class Solution {
public:
    
    int tree[100000][26+5],tot;
    int tag[100000];
    int used[100000];
    vector<int> visits;
    
    vector<int> findSubstring(string s, vector<string>& words) {
        vector<int> ans;ans.clear();
        if (s=="" || words.empty()) return ans;
        memset(tree,0,sizeof tree);
        memset(tag,0,sizeof tag);
        tot = 1;
        int lendic = words.size();
        for (int i = 0;i < lendic;i++){
            if (i>0 && ((int)words[i].size()!=(int)words[0].size())) return ans;
            string ts = words[i];
            int len2 = ts.size();
            int p = 1;
            for (int j = 0;j < len2;j++){
                if (tree[p][ts[j]-'a']==0){
                    tree[p][ts[j]-'a'] = ++tot;
                }
                p = tree[p][ts[j]-'a'];
            }
            tag[p]++;
        }
        int L = words[0].size();
        int len = s.size();
        for (int i = 0;i < len;i++){
            bool ok = true;
            visits.clear();
            for (int j = 0;j < lendic;j++){//要匹配字典里面的单词个数次
                int p = 1;
                for (int k = i+j*L;k < i+(j+1)*L;k++){//每次匹配的长度是固定的
                    if (k>=len){
                        ok = false;
                        break;
                    }
                    if (tree[p][s[k]-'a']==0){
                        ok = false;
                        break;
                    }
                    p = tree[p][s[k]-'a'];
                }
                if (!ok) break;
                if (tag[p]==0) { ok=false;break;}//如果字典里没有这个单词就停止
                if (used[p]==0) visits.push_back(p);//记录一下哪些位置用到了,之后清0用
                used[p]++;
                if (used[p]>tag[p]){//如果用的次数超过单词的个数了,则不行。
                    ok = false;
                    break;
                }
            }
            for (int x:visits) used[x]=0;
            if (ok) ans.push_back(i);
        }
        return ans;
    }
};
posted @ 2019-11-11 16:09  AWCXV  阅读(122)  评论(0编辑  收藏  举报