30. 串联所有单词的子串

时间:2019-09-14
本文章向大家介绍30. 串联所有单词的子串,主要包括30. 串联所有单词的子串使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

给定一个字符串 s 和一些长度相同的单词 words。找出 s 中恰好可以由 words 中所有单词串联形成的子串的起始位置。

注意子串要与 words 中的单词完全匹配,中间不能有其他字符,但不需要考虑 words 中单词串联的顺序。

示例 1:

输入:
s = "barfoothefoobarman",
words = ["foo","bar"]
输出:[0,9]
解释:
从索引 0 和 9 开始的子串分别是 "barfoor" 和 "foobar" 。
输出的顺序不重要, [9,0] 也是有效答案。
示例 2:

输入:
s = "wordgoodgoodgoodbestword",
words = ["word","good","best","word"]
输出:[]

/*
解题思路:
这道题让我们求串联所有单词的子串,就是说给定一个长字符串,
再给定几个长度相同的单词,让我们找出串联给定所有单词的子串的起始位置,
还是蛮有难度的一道题。假设 words 数组中有n个单词,每个单词的长度均为 len,
那么实际上这道题就让我们出所有长度为 n*len 的子串,使得其刚好是由 words 数组中的所有单词组成。
那么我们就需要经常判断s串中长度为 len 的子串是否是 words 中的单词,为了快速的判断,就要使用哈希表,
同时由于 words 数组可能有重复单词,所以就要用 HashMap 来建立所有的单词和其出现次数之间的映射,
即统计每个单词出现的次数。我们需要遍历s中所有长度为 n*len 的子串,当剩余子串的长度小于 n*len 时,
就不用再判断了。所以我们的i从0开始,到 (int)s.size() - n*len 结束就可以了,注意这里一定要将 s.size() 
先转为整型数,再进行解法。一定要形成这样的习惯,一旦 size() 后面要减去数字时,先转为 int 型,
因为 size() 的返回值是无符号型,一旦减去一个比自己大的数字,则会出错。对于每个遍历到的长度为 n*len 的子串,
需要验证其是否刚好由 words 中所有的单词构成,检查方法就是每次取长度为 len 的子串,看其是否是 words 中的单词。
为了方便比较,我们建立另一个 HashMap,一旦取出的单词不在 words 中,直接 break 掉,否则就将其在新的 HashMap 
中的映射值加1,还要检测若其映射值超过原 HashMap 中的映射值,也 break 掉,因为就算当前单词在 words 中,
但若其出现的次数超过 words 中的次数,还是不合题意的。在 for 循环外面,若j正好等于n,
说明我们检测的n个长度为 len 的子串都是 words 中的单词,并且刚好构成了 words,
则将当前位置i加入结果 res 即可

*/

#include<iostream>
#include<unordered_map>
#include<vector>
#include<string>
using namespace std;
class Solution {
public:
	vector<int> fs(string s, vector<string>& words)
	{
		if (s.empty() || words.empty())
			return{};
		vector<int> res;
		int n = words.size(), len = words[0].size();
		unordered_map<string, int> wordCnt;//unordered_map的迭代器是一个指针,指向这个元素,通过迭代器来取得它的值。
		for (auto &word : words)//for(auto &a : arr)中“auto &a”就是变量名就和上一个for循环中的“int i”一样,
			                    //与for(int i = 0; i<sizeof(arr); i++)是一样的。
			++wordCnt[word];
		for (int i = 0; i <= (int)s.size() - n * len; ++i)
		{
			unordered_map<string, int> strCnt;
			int j = 0;
			for (j = 0; j < n; ++j)
			{
				string t = s.substr(i + j * len, len);
				if (!wordCnt.count(t))
					break;
				++strCnt[t];
				if (strCnt[t] > wordCnt[t])
					break;
			}
			if (j == n)
				res.push_back(i);
		}
		return res;
	}
};

int main(){
	string s1;
	cin >> s1;
	string a[100];
	int x;
	int i = 0;
	vector<string>vec;
	while (cin >> a[i])
	{
			vec.push_back(a[i]);
			i++;//注意这里i++对输出结果的影响
			x = cin.get();
			if (x == '\n')
			  break;			
    }
	vector<int>ans = Solution().fs(s1, vec);
	for (int i = 0; i < ans.size(); i++)
	{
		cout << ans[i] << endl;
	}
	system("pause");
	return 0;
}

  

原文地址:https://www.cnblogs.com/277223178dudu/p/11519994.html