• leetcode30 串联所有单词的子串


    先对words中的单词排列组合,然后对s滑窗操作;部分样例超时,代码如下:

    class Solution {
    public:
        vector<int> findSubstring(string s, vector<string>& words) {
            //dfs找出words所有组合,然后在s滑窗
    
            //排除异常情况
            int len=0;
            for(auto w:words){
                len+=w.size();
            }
            if(len==0 || s.size()==0 || len>s.size()) return {};
            
            //排列组合words
            set<string> s_words;
            vector<int> indexs;
    
            for(int i=0;i<words.size();i++){
                indexs.push_back(i);
            }
            do{
                string tmp="";
                for(int i=0;i<indexs.size();i++){
                    tmp+=words[indexs[i]];
                }
                s_words.insert(tmp);
    
            }while(next_permutation(indexs.begin(),indexs.end()));
    
            //在s中滑窗寻找起始位置,O(m*n*k) m为s长度,n为s_words字符串个数,k为subs的长度;
            vector<int> res;     
            for(int i=0;i<=s.length()-len;i++){
                string subs=s.substr(i,len);           
                if(s_words.find(subs)!=s_words.end()){
                    res.push_back(i);
                }
            }
            return res;
        }
    };
    

    下面也超时,均执行至148/173

    class Solution {
    public:
        vector<int> findSubstring(string s, vector<string>& words) {
            //dfs找出words所有组合,然后在s滑窗
    
            //排除异常情况
            int len=0;
            for(auto w:words){
                len+=w.size();
            }
            if(len==0 || s.size()==0 || len>s.size()) return {};
    
            //排列组合words
            set<string> s_words;
            vector<int> indexs;
    
            for(int i=0;i<words.size();i++){
                indexs.push_back(i);
            }
            do{
                string tmp="";
                for(int i=0;i<indexs.size();i++){
                    tmp+=words[indexs[i]];
                }
                s_words.insert(tmp);
    
            }while(next_permutation(indexs.begin(),indexs.end()));
    
            //在s中滑窗寻找起始位置,O(m*n*k) m为s长度,n为s_words字符串个数,k为subs的长度;
            vector<int> res;     
            for(int i=0;i<=s.length()-len;i++){
                string subs=s.substr(i,len);           
                for(auto it=s_words.begin();it!=s_words.end();it++){
                    string tmp=*it;
                    int flag=1;
                    for(int j=0;j<len;j++){
                        if(tmp[j]!=subs[j]){
                            flag=0;break;
                        }
                    }
                    if(flag==1) {
                        res.push_back(i);break;
                    }
                }
            }
            return res;
        }
    };
    

    想办法对暴力算法进行提速,
    以下为别人的提速方案,可行;
    作者:Xdo
    链接:https://leetcode-cn.com/problems/substring-with-concatenation-of-all-words/solution/bao-li-suan-fa-jia-ru-qu-zhong-you-hua-10bei-ti-su/
    思路就是,先把存在的字符串,放到 hashmap ,可以快速比较,然后每一个位置都进行匹配
    但这里会有很多的重复计算,就可以使用一个小技巧,先计算目标串的每个字母的 ASCII 和,
    然后和当前要匹配的字符串的每个字母的 ASCII 进行比较,如果不相等就不用进行下面的匹配过程了

    class Solution {
    public:
        vector<int> findSubstring(string s, vector<string>& words) {
            vector<int> res;
            if(words.size()<1 || s.size()<1 || s.size() < words[0].size()*words.size()) return res;
            int wordLen = words[0].size(), lens = wordLen*words.size(), target = 0, cur = 0;
            unordered_map<string,int> allWord;
            for(auto& it:words){
                allWord[it]++;
                for(auto& i:it) target += i;
            }
            for(int i=0; i<lens; i++) cur += s[i];
            // 先看当前字符串的 ASCII 码相加是否相等 方便去重
            for(int i=0, j; i<=s.size()-lens; cur -= s[i], cur += s[lens + i++]){
                // 快速去重
                if(cur != target) continue;
                // 确认一下,是否为真的匹配
                unordered_map<string,int> tem(allWord);
                for(j=i; j<i+lens; j+=wordLen)
                    if(tem[s.substr(j, wordLen)]-- == 0) break;
                if(j == i+lens) res.push_back(i);
            }
            return res;
        }
    };
    
  • 相关阅读:
    7.12.2
    7.12.1
    7.11.8
    循环测试条件前缀和后缀的区别
    7.11.7 两个版本
    7.11.5
    7.12 vowels.c 程序
    7.11 animals.c 程序
    7.6.2 break 语句
    7.10 break.c 程序
  • 原文地址:https://www.cnblogs.com/joelwang/p/12071684.html
Copyright © 2020-2023  润新知