###### tags: `Leetcode` `medium` `sliding window` `python` `c++` `Top 100 Liked Questions`
# 438. Find All Anagrams in a String
## [題目連結:] https://leetcode.com/problems/find-all-anagrams-in-a-string/
## 題目:
Given two strings ```s``` and ```p```, return an array of all the start indices of ```p```'s anagrams in ```s```. You may return the answer in **any order**.
An **Anagram** is a word or phrase formed by rearranging the letters of a different word or phrase, typically using all the original letters exactly once.
**Example 1:**
```
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".
```
**Example 2:**
```
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
* 在s中找到p的所有anagrams的起始位置
* anagrams為字符種類各數均相同,順序可以不同
* Sliding Window:
* **slide Window size為 len( p )**
* 需要參數:
* res=[] :存anagrams start position
* cur_tmp=Counter() :統計目前拜訪的範圍中出現的字符與其次數
* python用collections.Counter()
* 也可以單純使用list[0] * 26 紀錄每個字母,因為題目規定一定是小寫,所以全部-'a'即可,(a為ASCII 97)
* countP=Counter(p): 統計p的字符種類與其次數,用來比較
* head=0
* tail=0
* Step1:
* 每次將s[tail]紀錄
* cur_tmp[s[tail]]+=1
* Step2: **若目前長度(tail-head+1)等於len(p),進入判斷**
* 若cur_tmp==countP,表示長度夠且符合anagrams
* res.append(head),將head紀錄於最終解
* **將head右移,讓後面tail能繼續遍歷**
* cur_tmp[s[head]]-=1
* 若cur_tmp[s[head]]為0,則需刪除
* head+=1
* Step3:
* tail+=1
## Python:
``` python=
from collections import Counter
class Solution(object):
def findAnagrams(self, s, p):
"""
:type s: str
:type p: str
:rtype: List[int]
"""
res=[] #存start pos
if len(s)<len(p):
return res
cur_tmp=Counter()
countP=Counter(p)
#slide winodw為len(p)
head=0
tail=0
while tail<len(s):
cur_tmp[s[tail]]+=1
if (tail-head+1)==len(p):
if cur_tmp==countP: #長度夠且符合
res.append(head)
#將head右移 給後面tail繼續找
cur_tmp[s[head]]-=1
if cur_tmp[s[head]]==0: #若為幽靈人口要刪除
del cur_tmp[s[head]]
head+=1
tail+=1
print(cur_tmp,res)
return res
s = "cbaebabacd"
p = "abc"
result=Solution()
ans=result.findAnagrams(s,p)
print(ans)
```
## Python: use array to store 26 letters
``` python=
class Solution:
def findAnagrams(self, s: str, p: str) -> List[int]:
head=0
tail=0
res=[]
countTmp=[0]*26
countP=[0]*26
for val in p:
countP[ord(val)-ord('a')]+=1
while tail<len(s):
countTmp[ord(s[tail])-ord('a')]+=1
if (tail-head+1)==len(p):
if countTmp==countP:
res.append(head)
countTmp[ord(s[head])-ord('a')]-=1
head+=1
tail+=1
return res
```
## C++:
``` cpp=
class Solution {
public:
vector<int> findAnagrams(string s, string p) {
int head=0, tail=0, lenS=s.size(), lenP=p.size();
vector<int> res;
vector<int> countTmp(26, 0), countP(26, 0);
for (auto val: p){
countP[val-'a']+=1;
}
while (tail<lenS){
countTmp[s[tail]-'a']+=1;
if ((tail-head+1)==lenP){
if (countTmp==countP)
res.push_back(head);
countTmp[s[head]-'a']-=1;
head+=1;
}
tail+=1;
}
return res;
}
};
```