网站图片轮播怎么弄,成都青羊网站建设,佛山微网站建设哪家专业,wordpress 扣积分题目描述
给定一个字符串 s 和一个字符串数组 words。 words 中所有字符串 长度相同。 s 中的 串联子串 是指一个包含 words 中所有字符串以任意顺序排列连接起来的子串。
例如#xff0c;如果 words [ab,cd,ef]#xff0c; 那么 如果 words [ab,cd,ef] 那么 abcdef abefcdcdabef cdefabefabcd 和 efcdab 都是串联子串。 acdbef 不是串联子串因为他不是任何 words 排列的连接。
返回所有串联子串在 s 中的开始索引。你可以以 任意顺序 返回答案。 示例 1
输入s barfoothefoobarman, words [foo,bar]
输出[0,9]
解释因为 words.length 2 同时 words[i].length 3连接的子字符串的长度必须为 6。
子串 barfoo 开始位置是 0。它是 words 中以 [bar,foo] 顺序排列的连接。
子串 foobar 开始位置是 9。它是 words 中以 [foo,bar] 顺序排列的连接。
输出顺序无关紧要。返回 [9,0] 也是可以的。示例 2
输入s wordgoodgoodgoodbestword, words [word,good,best,word]
输出[]
解释因为 words.length 4 并且 words[i].length 4所以串联子串的长度必须为 16。
s 中没有子串长度为 16 并且等于 words 的任何顺序排列的连接。
所以我们返回一个空数组。示例 3
输入s barfoofoobarthefoobarman, words [bar,foo,the]
输出[6,9,12]
解释因为 words.length 3 并且 words[i].length 3所以串联子串的长度必须为 9。
子串 foobarthe 开始位置是 6。它是 words 中以 [foo,bar,the] 顺序排列的连接。
子串 barthefoo 开始位置是 9。它是 words 中以 [bar,the,foo] 顺序排列的连接。
子串 thefoobar 开始位置是 12。它是 words 中以 [the,foo,bar] 顺序排列的连接。 提示
1 s.length 1041 words.length 50001 words[i].length 30words[i] 和 s 由小写英文字母组成 请问您在哪类招聘中遇到此题
1/5
社招
校招
实习
未遇到
通过次数
196.5K
提交次数
502.9K
通过率
39.1%
思路一暴力遍历通过178/179
字典字符串数组里每个单词的长度是固定的假设字典里有word_num个单词每个单词的长度为word_size。那么我们的任务就是在s中找到所有长度为word_num*word_size的子串判断这个子串能不能由字典里的单词串联起来其中串联指的是words里面的任意一个排列的连接。
这个方法的代码比较好写先用一个哈希表存放字典中每个单词出现的次数。每次判断子串时再创键一个新表遍历word_num个单词若某个单词在旧表中没有出现过或者是新表出现次数比旧表的多就说明这个子串不符合条件。
实现代码
class Solution {
public:unordered_mapstring,int mp;bool judge(string s,int wordNumber,int wordLength,int begin)//单词个数单词的字母个数{unordered_mapstring,int newMp;for(int ibegin;ibeginwordNumber*wordLength;iwordLength){string temps.substr(i,wordLength);if(mp.find(temp)mp.end()) return false;//字符串数组中没出现newMp[temp];if(newMp[temp]mp[temp]) return false;//多出现了}return true;}vectorint findSubstring(string s, vectorstring words) {vectorint ans;for(int i0;iwords.size();i){mp[words[i]];}int nwords.size(),mwords[0].size(),lss.length();int left0,rightn*m;for(int i0;ils-n*m;i){bool flagjudge(s,n,m,i);if(flag) ans.push_back(i);}return ans;}
};
思路二哈希表滑动窗口类KMP思想全部通过
我们学过kmp算法的都知道在字符串匹配时假设是在s串里寻找s1串如果比较懂s为下标is1为下标j的位置时发现两个串暂时不相等用BF算法的思想来说i要返回到i-j1的位置j要回到0的位置这里假设下标从0开始然后重新匹配。
但是按照kmp算法的思想来说既然s1已经比到了下标 j 的位置那么说明s1的前 j 个字符和s[i]的前j个字符是相等的而如果s1的最前面 k 个字符和s[i]的前 k 个字符相等的话i就不用回溯而 j 只需要回溯到第 k1 个位置就行。
总而言之kmp算法最核心的思想就是保留了之前搜索时的信息方便下一次搜索。
代码 class Solution {
public:vectorint findSubstring(string s, vectorstring words) {vectorint ans;int word_nums words.size();int word_size words[0].size();int ls s.length();unordered_mapstring, int mp1;for (int i 0; i word_nums; i)mp1[words[i]];for (int i 0; i word_size; i){int k;unordered_mapstring, int mp2;bool flag false;//表示同一个i下,上次匹配成功for (int j i; j word_nums * word_size ls; j word_size){//从下标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()) {//下标k之前包括下标k开始的子串都不用判断了j k;//jkword_size;外层的循环j还会加一次word_size//之前存储的结果也作废了flag false;mp2.clear();break;}else {mp2[temp];//重复次数过多时从下表j开始就不行了//重复出现的子串是temp所以只要从j开始寻找第一次出现temp的位置index然后从indexword_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;//indexword_size;外层循环会加一次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就从kword_size开始flag true;}}}return ans;}
};