美文网首页
LintCode 647. Substring Anagrams

LintCode 647. Substring Anagrams

作者: Andiedie | 来源:发表于2017-08-21 20:13 被阅读0次

原题

LintCode 647. Substring Anagrams

Description

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 40,000.

The order of output does not matter.

Example

Given s = "cbaebabacd" p = "abc"

return [0, 6]

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

解题

题意是给定一个字符串s和一个patternp,要求从s中找到p的任何一种排列出现的全部位置。
最最naive的解法就是首先对p进行全排列,然后在s中寻找每一种排列,不过这必然会超时。

合理的解法是:
假设s的长度为ssizep长度为psize
s进行窗口式的扫描,窗口的宽度为psize。也就是说每次都从s中取出psize个字符。

此时维护两个字母表,prr字母表用来记录p中所有字母出现的次数,srr字母表用来记录当前扫描的窗口中的所有字母的出现次数。

此时如果两个字母表相同,则表明窗口中的字符串p的字母构成是一致的,也就是说窗口中的字符串是p的一个排列,那么只需要将窗口的起始位置加入答案即可。

优化

上述解法是,每次窗口移动的时候都统计一遍srr字母表,这做了很多无用功。
我们可以采用下述策略来维护字母表srr
首次扫描的时候,完整统计窗口内所有字母的出现次数。
之后每次移动窗口的时候,将移出窗口的字母出现的次数 -1,将移入窗口的字母出现的次数 +1

代码

class Solution {
public:
    /**
    * @param s a string
    * @param p a non-empty string
    * @return a list of index
    */
    vector<int> findAnagrams(string& s, string& p) {
        // Write your code here
        // 答案集合
        vector<int> ans;
        // 两个字母表
        int srr[26] = { 0 }, prr[26] = { 0 };
        int ssize = s.size(), psize = p.size();
        if (ssize < psize) return ans;
        // 首次扫描,完整统计窗口内字母出现的次数
        for (int i = 0; i < psize; i++) srr[s[i] - 'a']++;
        // 统计p中字母出现的次数
        for (int i = 0; i < psize; i++) prr[p[i] - 'a']++;
        for (int j = psize; j <= ssize; j++) {
            bool isOK = true;
            for (int i = 0; i < 26; i++) {
                if (srr[i] != prr[i]) {
                    isOK = false;
                    break;
                }
            }
            // 如果字母表完全相同,则将窗口初始位置加入答案
            if (isOK) ans.push_back(j - psize);
            if (j == ssize) return ans;
            // 将移入窗口的字母出现次数 + 1
            srr[s[j] - 'a']++;
            // 将移出窗口的字母出现次数 - 1
            srr[s[j - psize] - 'a']--;
        }
        return ans;
    }
};

相关文章

网友评论

      本文标题:LintCode 647. Substring Anagrams

      本文链接:https://www.haomeiwen.com/subject/rhphdxtx.html