1. 程式人生 > 其它 >30串聯所有單詞的子串

30串聯所有單詞的子串

技術標籤:leetCode 題目leetcode字串第30題目c++

30串聯所有單詞的子串

題目難度:困難

題目要求:

給定一個字串s和一些長度相同的單詞words。找出 s 中恰好可以由words 中所有單詞串聯形成的子串的起始位置。

注意子串要與words 中的單詞完全匹配,中間不能有其他字元,但不需要考慮words中單詞串聯的順序。

示例 1:

輸入:
s = "barfoothefoobarman",
words = ["foo","bar"]
輸出:[0,9]
解釋:
從索引 0 和 9 開始的子串分別是 "barfoo" 和 "foobar" 。

輸出的順序不重要, [9,0] 也是有效答案。
示例 2:

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

解題思路:
首先考慮的當然是匹配問題,如果常規的去匹配字串,需要大量的匹配的時間,於是採用hashmap的方式,這樣就可以查詢每次的複雜度都是1了。然後每個字串都是數量相等的,這樣就可以拆分,可以想到雙指標。然後就是返回的東西了。細節比較多。

vector<int> findSubstring(string s, vector<string>& words) {
	if (words.size() == 0) return{};
	unordered_map<string, int> wordcnt;
	for (auto& w : words) {
		wordcnt[w]++;
	}
	int len = words[0].size();

	vector<int> ans;
	for (int i = 0; i < len; i++) {
		int left = i;
		int right = left;
		int cnt = 0;

		unordered_map<string, int> window;
		while (left + words.size() * len <= s.size()) {
			string temp = "";
			while (cnt < words.size()) {
				temp = s.substr(right, len);
				if (wordcnt.find(temp) == wordcnt.end() || window[temp] >= wordcnt[temp]) break;
				window[temp]++;
				cnt++;
				right += len;
			}

			if (window == wordcnt) {
				ans.push_back(left);
			}

			if (wordcnt.find(temp) != wordcnt.end()) {
				window[s.substr(left, len)]--;
				cnt--;
				left += len;
			}
			else {
				right += len;
				left = right;
				cnt = 0;
				window.clear();
			}
		}
	}
	return ans;
}