Substring with Concatenation of All Words字符串中找到包含所有单词的子串

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).

这道题相对来说还是比较简单的, 题意中规定了所有的单词长度是一样的.

所以大致考察的就是字符串的查找. 自己做过后网上发现解决的代码更加清晰, 值得学习, 所以记录在这里:


#include <iostream>
#include <vector>
#include <map>
#include <string>
using namespace std;

class Solution {
public:
/*    vector<int> findSubstring(string s, vector<string>& words) {
        int nWords = words.size();
        int wordsLen = words[0].size();
        vector<int> ret;
        map<string, int> Map;
        
        for(int i=0; i<nWords; i++){
		map<string, int>::iterator it = Map.find(words[i]);
		if(it == Map.end())
			Map[words[i]] = 1;
		else
			Map[words[i]] = Map[words[i]] + 1;
	}
        
        int strLen = s.size();
        map<string, int>::iterator it;
        int i = 0;
	//cout << "strLen = " << strLen << endl;
        while(i<strLen) {
            map<string, int> Store;
	    int curSize = 0;
            if((strLen - i) < (nWords * wordsLen))
                return ret;

            string word(s.begin()+i, s.begin()+i+wordsLen);
            it = Map.find(word);
	    //cout << "i = " << i << endl;
            if(it == Map.end()){
		i++;
                continue;
	    }
            else{
                Store[word] = 1;
		curSize ++;
		if(curSize == nWords){
                    ret.push_back(i);
                    i ++;
                    continue;
                }
                for(int j = i+wordsLen; ; j += wordsLen){
                    string word(s.begin()+j, s.begin()+j+wordsLen);
		    //cout << "j is " << j << " and word is " << word << " and curSize is " << curSize << endl;
                    it = Map.find(word);
                    if(it == Map.end()){
                        i ++;
                        break;
                    }
                    else{
                        map<string, int>::iterator itt;
                        itt = Store.find(word);
                        if(itt == Store.end()){
			    curSize ++;
                            Store[word] = 1;
			    //cout << "--------now size is " << curSize << endl;
                            if(curSize == nWords){
                                ret.push_back(i);
                                i ++;
                                break;
                            }
                        }
                        else{
                            if(Store[word] == Map[word]){
			    	i ++;
                            	break;
			    }
			    else{
			        curSize ++;
			    	Store[word] = Store[word] + 1;
                            	if(curSize == nWords){
                                    ret.push_back(i);
                                    i ++;
                                    break;
                                }
			    }
                        }
                    }
                }
            }
	    //cout << "i is changed to " << i << endl;
        }
        
        return ret;
    }
*/

	//almost a same solution, but a better implement
	vector<int> findSubstring(string s, vector<string>& words) {
		int strLen = s.size();
		int nWords = words.size();
		int wordLen = words[0].size();

		vector<int> ret;
		map<string, int> Map;
		//将单词放到map中, key为string, value为该单词出现的次数
        	for(int i=0; i<nWords; i++){
			if(Map.find(words[i]) == Map.end())
				Map[words[i]] = 1;
			else
				Map[words[i]]++;
		}

		//既然题目说明了, 每个单词的长度是相同的. 那么我们以后就是按照单词的长度来判断一个单词是否为words中存在的
		//比如单词长度为4, 那么就是每4个字母组成一个单词进行比较
		//要把所有长度为4的单词都访问一遍的方法是用两层for循环, 像这样:
		//[a ,b, c, d, e, f, g, h] 的话所有长度为4的单词有: (abcd, bcde, cdef, defg, efgh)
		//for(int i=0; i<4; i++)
		//	for(int j=i; j<=len-4; j+=l)
		//		string.substr(j, 4);
		for(int i=0; i<wordLen; i++){
			map<string, int> Store;
			int curSize = 0;
			//这个变量用于二层循环的start. 因为如果abcd不满足, 还是要继续查找下去. 接下里就是从efgh开始查找
			int windLeft = i;
			cout << "i = " << i << endl;
			for(int j=i; j<=strLen-wordLen; j+=wordLen){
				string word = s.substr(j, wordLen);
				if(Map.find(word) == Map.end()){
					Store.clear();
					curSize = 0;
					windLeft = j+wordLen;
					continue;
				}

				//该单词符合条件, 那么继续看是否满足出现的次数要求. 比如给定的words中出现多个abcd
				curSize ++;
				if(Store.find(word) == Store.end())
					Store[word] = 1;
				else
					Store[word]++;

 				//出现次数过多了, 那么比如我只要两个, 居然出现了三个. 那么下次就从第一个这个单词出现的后面开始继续查找
				string tmp;
				if(Store[word] > Map[word]){
					do{
						tmp = s.substr(windLeft, wordLen);
						Store[tmp] --;
						curSize --;
						windLeft += wordLen;
					}while(tmp != word);
				}

				//出现了满足题目要求的了,将开始下标(即windLeft)放到结果vector中去
				if(curSize == nWords){
					ret.push_back(windLeft);
					//可能给定的words是{"abcd", "efgh"}
					//给定的s是 "abcdefghabcd", 这里面存在两对呢.
					//于是在得到第一个结果后, 把最左边的元素"abcd"删掉, 把efgh作为开头继续寻找
					string tmp = s.substr(windLeft, wordLen);
					Store[tmp]--;
					curSize--;
					windLeft += wordLen;
				}
			}
		}

		return ret;
	}
};

int main()
{
	Solution x;
	string s("lingmindraboofooowingdingbarrwingmonkeypoundcake");
	vector<int> ret;
	vector<string> v;
	v.push_back("fooo");
	v.push_back("barr");
	v.push_back("wing");
	v.push_back("ding");
	v.push_back("wing");
	ret = x.findSubstring(s, v);
	cout << ret.size() <<endl;
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值