【C++】 LeetCode 30. Substring with Concatenation of All Words

题目:

You are given a string, s, and a list of words, words, that are all of the same length. Find all starting indices of substring(s) in s that is a concatenation of each word in words exactly once and without any intervening characters.

For example, given:
s"barfoothefoobarman"
words["foo", "bar"]

You should return the indices: [0,9].
(order does not matter).

运行结果:

运行时间为33ms

解析:

这道题意思是给定长字符串s,和一个字符串数组words,用words中的字符串组成s的一个子串,求解子串的起始位置,其中words中的字符串必须全部使用且只能使用一次,words中可以存在重复字符串,组合时不考虑words中字符串的顺序。

思路:

这道题比较复杂。由于words中存在重复字符串,故采用map<string,int>来记录words中每个字符串出现的次数,用count记录words中字符串总数。lenWords表示Words中字符串长度
遍历时不能对s中字符逐个遍历,否则会超时。采用间隔遍历。每次遍历时将s切割为多个长度为lenWords的字符串,每个字符串作为一个整体来考虑。就可以采用双指针方式来解决。
比如
s "barfoothefoobarman"
words ["foo", "bar"]
由于words中每个字符串为3个字符,则遍历的时候分为三组:0,3,6,9,12,15;1,4,7,10,13,16;2,5,8,11,14,17;对于每组分别遍历求解。
以第一组0,3,6,9,12,15为例, s "barfoothefoobarman" ,可以划分为bar foo the foo bar man,采用两个指针,后指针指向起始值,前指针进行遍历,每找到一个符合字符串则map对应的值--,count--,如果count=0则找到一个子串,将后指针所指位置加入结果中。

代码:

class Solution {
public:
    vector<int> findSubstring(string s, vector<string>& words) {
        int lenWords=words.size();
        int lens=s.size();
        vector<int> res;
        if(lenWords==0||lens==0)return res;
        int singlelen=words[0].size();
        int count=lenWords;
        map<string,int> use;
        //初始化map
        use.clear();
        for(int i=0;i<words.size();i++){
            string temp=words[i];
            use[temp]++;
        }    
        
        //外层循环控制分组遍历
        for(int start=0;start<singlelen;start++){
            int pre=start;
            string str;
            // double points
            for(int i=start;i<=lens-singlelen;i+=singlelen){
                pre=pre>i?pre:i;
                while(pre+singlelen<=lens){
                    str=s.substr(pre,singlelen);
                    if(use.count(str)!=0&&use[str]!=0){
                        use[str]--;
                        count--;
                        pre+=singlelen;
                        if(count==0){
                            res.push_back(i);
                            break;
                        }
                    }
                    else{
                        break;
                    }
                }
                if(use.count(s.substr(i,singlelen))!=0){
                    use[s.substr(i,singlelen)]++;
                    count++;
                } 
            }
        }
        return res;
    }
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值