给定一个字符串 s 和一个非空字符串 p,找到 s 中所有是 p 的字母异位词的子串,返回这些子串的起始索引。
字符串只包含小写英文字母,并且字符串 s 和 p 的长度都不超过 20100。
说明:
字母异位词指字母相同,但排列不同的字符串。
不考虑答案输出的顺序。
示例 1:
输入:
s: "cbaebabacd" p: "abc"
输出:
[0, 6]
解释:
起始索引等于 0 的子串是 "cba", 它是 "abc" 的字母异位词。
起始索引等于 6 的子串是 "bac", 它是 "abc" 的字母异位词。
示例 2:
输入:
s: "abab" p: "ab"
输出:
[0, 1, 2]
解释:
起始索引等于 0 的子串是 "ab", 它是 "ab" 的字母异位词。
起始索引等于 1 的子串是 "ba", 它是 "ab" 的字母异位词。
起始索引等于 2 的子串是 "ab", 它是 "ab" 的字母异位词。
这到题目,可以找到s中所有长度等于p的字符串子串,判断是否时是异位词,判断是异位词,可以用Hash在O(k)的时间比较,也可以用排序的方法在O(klogk)的时间比较。
这样总的时间复杂度大概是O(N^2)的级别
这个可以用滑窗的方法,在O(N)的时间中解决。方法是先用一个Hash表存下字符串p中每个字符以及出现的次数。
然后左区间指针i和又区间指针j从0开始滑动,当窗口大小小于p.size()的时候,i指针不动,j指针向右滑动,Hash[s[j]-'a']--, 如果--后的Hash[s[j]-'a']>=0,说明p中有这个数,那么count++, 当count=p.size()时,说明i,j区间就是异位字符。
当j>=p.size()的时候,i每次向右移动一个位置,此时Hash[s[i]-'a']++, 即还原操作,如果出现Hash[s[i]-'a']>0, 说明原来这个值就是>0的,count要--
class Solution {
public:
vector<int> findAnagrams(string s, string p)
{
if(s.size()<p.size()) return {};
int hash[26] ={0}; // 开一个数组当Hash表
for(auto c:p) hash[c-'a']++; // 先存一遍p
vector<int> res;
int count = 0; // count保存窗口中满足要求字符串的个数
for(int i=0,j=0;j<s.size();j++){
hash[s[j]-'a']--;
if(hash[s[j]-'a']>=0) count++;
// 开始i不动j一直滑动到p.size()-1
// 当移动到p.size()的位置时,i开始移动
if(j>p.size()-1){
hash[s[i]-'a']++;
if(hash[s[i]-'a']>0) count--; // 说明这个字符在p中出现
i++;
}
// 跟新结果
if(count==p.size())
res.push_back(i);
}
return res;
}
};
'