給定兩個字符串?s
?和?p
,找到?s
?中所有?p
?的?異位詞?的子串,返回這些子串的起始索引。不考慮答案輸出的順序。
異位詞?指由相同字母重排列形成的字符串(包括相同的字符串)。
示例?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" 的異位詞。
提示:
1 <= s.length, p.length <= 3 * 104
s
?和?p
?僅包含小寫字母
題解
一開始是想用兩層循環,先將p排序一次,然后將s中每個和p一樣長的子串拿出來重新排序之后和p比較是否相同,但是這種做法會超時
于是采用了官方的解法,官方的做法有兩個優點,一個是利用了滑動窗口,另一個是將判斷異位詞轉換成判斷每個字母出現的次數是否相同,這個確實是最快判斷是否是由相同字母組成的字符串的方法
class Solution {
public:vector<int> findAnagrams(string s, string p) {vector<int>answer;int sLength=s.size(),pLength=p.size();if(sLength<pLength){ // 如果s短于p,后面無法放置窗口return {};}vector<int>ss(26),pp(26); // 記錄字母出現次數for(int i=0;i<pLength;i++){ // 放置滑動窗口ss[s[i]-'a']++;pp[p[i]-'a']++;}if(ss==pp)answer.emplace_back(0);for(int i=0;i<sLength-pLength;i++){ss[s[i]-'a']--; // 滑動窗口移動,去掉前一個字母的狀態ss[s[i+pLength]-'a']++; // 滑動窗口移動,增加后一個字母的狀態if(ss==pp)answer.emplace_back(i+1);}return answer;}
};