[LeetCode-438][找到字符串中所有字母异位词][Find All Anagrams in a String]

原题

链接:https://leetcode-cn.com/problems/find-all-anagrams-in-a-string

【中文】

给定一个字符串 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" 的字母异位词。

【英文】

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.
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".

题解思路:

  题目中是对目标子串p的各种组合的查找,即在字符串s中查找子串中的字符均在p中,且出现次数与目标子串p中的次数即可。采用滑动窗口方法,具体如下。

  1.   首先,建立目标子串的标记数组mark[],用于标记字符串p中各字母出现的次数。
  2.   其次,从字符串s的位置0开始向后建立滑动窗口,以匹配字符串p中字母均有出现的情况。
    • 将窗口右位置r处的字母mark-1,展开窗口。
    • 若mark[s[r]]>=0,则r处字母在目标子串p中,已匹配字符的长度len增加1.
  3.   窗口向右移动。窗口左位置l,右位置r,窗口长度(r-l+1), 目标匹配字符串p的长度pLen。当窗口长度(r-l+1) > pLen时,将窗口向右移动。
    • 将窗口左位置l的字母mark恢复+1,
    • 若mark[s[l]] > 0,则表示该字母在目标子串中,需要将已匹配长度len减小1;否则,mark[s[l]]会为0;
    • 窗口左位置l++,窗口完成右移。
  4.   确认已找到符合要求的子串。当已匹配的字符串长度len和目标子串p长度相等,则表明已找到一个符合要求的子串。

代码: 

  

 1 /**
 2  * Note: The returned array must be malloced, assume caller calls free().
 3  */
 4 #define MARK_SIZE (256)
 5 #define MAX_STRING_SIZE (20100) 
 6 
 7 int* findAnagrams(char * s, char * p, int* returnSize){
 8     int mark[MARK_SIZE] =  { 0 };
 9     int *result = NULL;
10     int slen = strlen(s);
11     int plen = strlen(p);
12     int i;
13     int l;
14     int r;
15     int len;
16     int count = 0;
17     *returnSize = 0;
18     printf("slen=%d, plen=%d\n",slen,plen);
19     for (i = 0; i < MARK_SIZE; i++)
20         mark[i] = 0;
21     result = (int*)malloc(sizeof(int)*(MAX_STRING_SIZE));
22     for (i = 0; i < plen; i++) {
23         mark[p[i]]++;
24         printf("mark[%c] = %d\n", p[i],mark[p[i]]);
25     }
26     for(l = 0, r = 0, len = 0; r < slen; r++) {
27         mark[s[r]]--;
28         if(mark[s[r]]>=0)
29             len++;
30         while(r - l + 1 > plen) {
31             mark[s[l]]++;
32             if (mark[s[l]] > 0) {
33                 len--;
34             }
35             l++;
36         }
37         if(len == plen)
38         {
39             result[*returnSize] = l;
40             (*returnSize)++;
41             printf("returnSize=%d, l=%d r=%d\n",*returnSize,l,r);
42         }
43     }
44     return result;
45 }

 

posted @ 2020-02-06 22:04  稀里糊涂的胡闹  阅读(66)  评论(0)    收藏  举报