外貿(mào)網(wǎng)站如何做的好處站長工具seo綜合查詢怎么使用的
題目描述
給定一個字符串?s
?和一個字符串?dāng)?shù)組?words
。?words
?中所有字符串?長度相同。
?s
?中的?串聯(lián)子串?是指一個包含??words
?中所有字符串以任意順序排列連接起來的子串。
- 例如,如果?
words = ["ab","cd","ef"]
, 那么?"abcdef"
,?"abefcd"
,"cdabef"
,?"cdefab"
,"efabcd"
, 和?"efcdab"
?都是串聯(lián)子串。?"acdbef"
?不是串聯(lián)子串,因?yàn)樗皇侨魏?words
?排列的連接。
返回所有串聯(lián)子串在?s
?中的開始索引。你可以以?任意順序?返回答案。
示例 1:
輸入:s = "barfoothefoobarman", words = ["foo","bar"]
輸出:[0,9]
解釋:因?yàn)?words.length == 2 同時 words[i].length == 3,連接的子字符串的長度必須為 6。
子串 "barfoo" 開始位置是 0。它是 words 中以 ["bar","foo"] 順序排列的連接。
子串 "foobar" 開始位置是 9。它是 words 中以 ["foo","bar"] 順序排列的連接。
輸出順序無關(guān)緊要。返回 [9,0] 也是可以的。
示例 2:
輸入:s = "wordgoodgoodgoodbestword", words = ["word","good","best","word"]
輸出:[]
解釋:因?yàn)?strong> words.length == 4 并且 words[i].length == 4,所以串聯(lián)子串的長度必須為 16。
s 中沒有子串長度為 16 并且等于 words 的任何順序排列的連接。
所以我們返回一個空數(shù)組。
示例 3:
輸入:s = "barfoofoobarthefoobarman", words = ["bar","foo","the"] 輸出:[6,9,12] 解釋:因?yàn)?words.length == 3 并且 words[i].length == 3,所以串聯(lián)子串的長度必須為 9。 子串 "foobarthe" 開始位置是 6。它是 words 中以 ["foo","bar","the"] 順序排列的連接。 子串 "barthefoo" 開始位置是 9。它是 words 中以 ["bar","the","foo"] 順序排列的連接。 子串 "thefoobar" 開始位置是 12。它是 words 中以 ["the","foo","bar"] 順序排列的連接。
提示:
1 <= s.length <= 104
1 <= words.length <= 5000
1 <= words[i].length <= 30
words[i]
?和?s
?由小寫英文字母組成
請問您在哪類招聘中遇到此題?
1/5
社招
校招
實(shí)習(xí)
未遇到
通過次數(shù)
196.5K
提交次數(shù)
502.9K
通過率
39.1%
思路一,暴力遍歷,通過178/179
字典(字符串?dāng)?shù)組)里每個單詞的長度是固定的,假設(shè)字典里有word_num個單詞,每個單詞的長度為word_size。那么我們的任務(wù)就是在s中找到所有長度為word_num*word_size的子串,判斷這個子串能不能由字典里的單詞串聯(lián)起來(其中串聯(lián)指的是words里面的任意一個排列的連接)。
這個方法的代碼比較好寫,先用一個哈希表存放字典中每個單詞出現(xiàn)的次數(shù)。每次判斷子串時再創(chuàng)鍵一個新表,遍歷word_num個單詞,若某個單詞在舊表中沒有出現(xiàn)過或者是新表出現(xiàn)次數(shù)比舊表的多,就說明這個子串不符合條件。
實(shí)現(xiàn)代碼:
class Solution {
public:unordered_map<string,int> mp;bool judge(string& s,int wordNumber,int wordLength,int begin)//單詞個數(shù),單詞的字母個數(shù){unordered_map<string,int> newMp;for(int i=begin;i<begin+wordNumber*wordLength;i+=wordLength){string temp=s.substr(i,wordLength);if(mp.find(temp)==mp.end()) return false;//字符串?dāng)?shù)組中沒出現(xiàn)newMp[temp]++;if(newMp[temp]>mp[temp]) return false;//多出現(xiàn)了}return true;}vector<int> findSubstring(string s, vector<string>& words) {vector<int> ans;for(int i=0;i<words.size();i++){mp[words[i]]++;}int n=words.size(),m=words[0].size(),ls=s.length();int left=0,right=n*m;for(int i=0;i<=ls-n*m;i++){bool flag=judge(s,n,m,i);if(flag) ans.push_back(i);}return ans;}
};
思路二:哈希表+滑動窗口+類KMP思想,全部通過
我們學(xué)過kmp算法的都知道,在字符串匹配時(假設(shè)是在s串里尋找s1串),如果比較懂s為下標(biāo)i,s1為下標(biāo)j的位置時發(fā)現(xiàn)兩個串暫時不相等,用BF算法的思想來說i要返回到i-j+1的位置,j要回到0的位置(這里假設(shè)下標(biāo)從0開始),然后重新匹配。
但是按照kmp算法的思想來說,既然s1已經(jīng)比到了下標(biāo)? j? 的位置,那么說明s1的前 j 個字符和s[i]的前j個字符是相等的,而如果s1的最前面 k 個字符和s[i]的前 k 個字符相等的話,i就不用回溯,而 j 只需要回溯到第 k+1 個位置就行。
總而言之,kmp算法最核心的思想就是保留了之前搜索時的信息,方便下一次搜索。
代碼:
?
class Solution {
public:vector<int> findSubstring(string s, vector<string>& words) {vector<int> ans;int word_nums = words.size();int word_size = words[0].size();int ls = s.length();unordered_map<string, int> mp1;for (int i = 0; i < word_nums; i++)mp1[words[i]]++;for (int i = 0; i < word_size; i++){int k;unordered_map<string, int> mp2;bool flag = false;//表示同一個i下,上次匹配成功for (int j = i; j + word_nums * word_size <= ls; j += word_size){//從下標(biāo)j開始的子串if (!flag) k = j;for (; k < j + word_nums * word_size; k += word_size){string temp = s.substr(k, word_size);if (mp1.find(temp) == mp1.end()) {//下標(biāo)k之前(包括下標(biāo)k)開始的子串都不用判斷了j = k;//j=k+word_size;外層的循環(huán)j還會加一次word_size//之前存儲的結(jié)果也作廢了flag = false;mp2.clear();break;}else {mp2[temp]++;//重復(fù)次數(shù)過多時,從下表j開始就不行了//重復(fù)出現(xiàn)的子串是temp,所以只要從j開始尋找第一次出現(xiàn)temp的位置index,然后從index+word_size開始匹配if (mp2[temp] > mp1[temp]) {int index = j;string t = s.substr(index, word_size);while (t != temp) {index += word_size;mp2[t]--;t = s.substr(index, word_size);}j = index + word_size;//index+=word_size;外層循環(huán)會加一次word_sizemp2[temp]--;}}}//從j開始的子串完全匹配if (k == j + word_nums * word_size){ans.push_back(j);//移除從j開始的子串的第一個單詞string t = s.substr(j, word_size);mp2[t]--;if (mp2[t] == 0) mp2.erase(t);//k += word_size;//只有一個單詞沒有匹配好,所以從k就從k+word_size開始flag = true;}}}return ans;}
};