题目

思路
- 滑动窗口,窗口内维护所需要的字符,在所需要的字符都满足后,因为我们需要的是窗口的左端点,所以此时尽可能收缩左端点,把不合法的字符排除掉的
- 为了实时知道我们还需要哪些字符,以及什么时候,窗口已然包含了我们所需的所有字符了,可以用一个计数数组need[]来记录窗口内字符的情况
代码
vector<int> findAnagrams(string s, string p)
{
auto n = s.size()
auto m = p.size()
vector<int> ans
int needCnt = m
vector<int> need(123,0)
//need['a'] = 1
//need['b'] = 1
//need['c'] = 1
//need[x] > 0: 需要字符x,数值=需要该字符的数量
//need[x] < 0: 字符x多余
for(const char& c:p)
{
need[c]++
}
int L = 0
int R = 0
while(R < n)
{
char c = s[R]
R++
if(need[c] > 0)//若是目标字符,则还需要的字符数--
{
needCnt--
}
need[c]--
if(needCnt == 0)//所有需要的字符都有了,收缩左窗口,看有没有多余的字符(need[x]<0)
{
while(L < R && need[s[L]] < 0)//s[L]是多余的,可以收缩窗口
{
need[s[L]]++
L++
}
if(R-L == m)//因为L...R中间可能存在多余的字符,这种情况左端点收缩也没办法把这些多余的排除,所以必须这样判断筛选合法的答案
{
ans.push_back(L)
}
}
}
return ans
}
总结
- 需要找一个包含指定多个字符的连续子串,可以用滑动窗口解决,期望窗口内部就包含所有需要的字符。窗口右端点R去寻找字符,左端点适时收缩以排除不需要的字符,整体目标是维护窗口内的字符都是所需要的
- 为了知道窗口内部的字符情况,比如哪些是多余的,哪些是需要的,可以用计数数组
need[],滑动窗口左右端点更新的时候,计数数组同步更新
- 上面代码还是可以改进的,或者说,有另一种方法。在第一次找到合法L后,cnt=0,而没有重置,意味着后续的合法L,其实都只能通过收缩左端点L找到