问题描述:
Given a string s and a non-empty string p, find all the start indices of p's anagrams in s.
Strings consists of lowercase English letters only and the length of both strings s and p will not be larger than 20,100.
The order of output does not matter.
示例:Input: s: "cbaebabacd" p: "abc" Output: [0, 6] Explanation: The substring with start index = 0 is "cba", which is an anagram of "abc". The substring with start index = 6 is "bac", which is an anagram of "abc".
Input: s: "abab" p: "ab" Output: [0, 1, 2] Explanation: The substring with start index = 0 is "ab", which is an anagram of "ab". The substring with start index = 1 is "ba", which is an anagram of "ab". The substring with start index = 2 is "ab", which is an anagram of "ab".问题分析:
求解s中所有以p颠倒顺序的所成子串索引值,我们可以用滑动窗口法来求解。
1.以p的长度为窗口长度,统计窗口内出现s和p的字母的次数sv和pv
2.在s中每次窗口向右滑动一个字母,统计该字母的次数,在sv中除去左边的一个字母,以维持滑动窗口大小不变
3.比较sv和pv是否相同,若相同,则把s中对应的索引添加进结果集中去。
过程详见代码:
class Solution {
public:
vector<int> findAnagrams(string s, string p) {
vector<int> pv(26,0), sv(26,0), res;
if(s.size() < p.size())
return res;
// fill pv, vector of counters for pattern string and sv, vector of counters for the sliding window
for(int i = 0; i < p.size(); ++i)
{
++pv[p[i]-'a'];
++sv[s[i]-'a'];
}
if(pv == sv)
res.push_back(0);
//here window is moving from left to right across the string.
//window size is p.size(), so s.size()-p.size() moves are made
for(int i = p.size(); i < s.size(); ++i)
{
// window extends one step to the right. counter for s[i] is incremented
++sv[s[i]-'a'];
// since we added one element to the right,
// one element to the left should be forgotten.
//counter for s[i-p.size()] is decremented
--sv[s[i-p.size()]-'a'];
// if after move to the right the anagram can be composed,
// add new position of window's left point to the result
if(pv == sv)
res.push_back(i-p.size()+1);
}
return res;
}
};