• 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 == '
    ')
    			  break;			
        }
    	vector<int>ans = Solution().fs(s1, vec);
    	for (int i = 0; i < ans.size(); i++)
    	{
    		cout << ans[i] << endl;
    	}
    	system("pause");
    	return 0;
    }
    

      

  • 相关阅读:
    UVA 10935 约瑟夫环
    分拆素数和 埃氏筛法
    POJ 2349 Prim
    POJ 2031 prim
    POJ 1861 Kruskal
    POJ 2395 Prim
    POJ 1751 Prim
    POJ 2421 Prim
    vuejs开发环境搭建及热更新
    vuejs介绍
  • 原文地址:https://www.cnblogs.com/277223178dudu/p/11519994.html
Copyright © 2020-2023  润新知