解法:滑动窗口+双指针
先用一个循环遍历子串,使用一个vector记录子串中每个字母出现的次数(第几个字母就是vecot的下标值,vector值代表出现次数)
第二个循环主要是移动窗口右边界,每当出现多于子串p的字母时,开始移动左边界限,直到左边界移动到 1.没出现过的字母右侧 or 2.将多出的重复字母移出停止,最后处理维护窗口数正好时p的长度时即为结果
vector<int> findAnagrams(string s, string p) {
int l=p.size();
vector<int> mpp(26,0);
vector<int> mps(26,0);
vector<int> ans;
//记录子串各个字母数
for(int i=0;i<l;i++){
mpp[p[i]-'a']++;
}
int left=0;
for(int j=0;j<s.size();j++){
int curRight=s[j]-'a';
mps[curRight]++;
//sArr[curRight] > pArr[curRight] 则说明
//1. 出现了p中没有的字符 eg: s=cbae p=abc, 指针到s中的e时, sArr['e'-'a'] = 1 > pArr['e'-'a'] = 0
//2. 出现了s中这个字符大于p中这个字符数量
//所以需要移动左下标了 要缩小窗口, 因为我们窗口只匹配完全对应p的
// left++ 同时left所指的字符sArr[curLeft]也要改变
while(mps[curRight]>mpp[curRight]){
int curLeft=s[left]-'a'; //找左侧字母位数
mps[curLeft]--; //滑动窗口移出最左侧字母
left++; //缩小左窗口
}
//维护窗口数正好时p的长度
//从始至终, 代码走到这个地方, 窗口的大小都不超过p的长度
//凡是超过了的, 多被while(sArr[curRight] > pArr[curRight]) 这个循环缩小了窗口范围
if(j - left + 1 == p.size()){
ans.push_back(left);
}
}
return ans;
}