C++ 中查找字符串中的所有字谜


假设我们有一个字符串 s 和一个非空字符串 p,我们需要找到 p 的所有字谜在 s 中的起始索引。字符串仅包含小写字母,并且字符串 s 和 p 的长度都不会大于 20 和 100。例如,如果 s:“cbaebabacd” p:“abc”,则输出将为 [0, 6],在索引 0 处,它是“cba”,另一个是“bac”,这些都是“abc”的字谜。

为了解决这个问题,我们将遵循以下步骤:

  • 定义一个映射 m,n := s 的大小,设置 left := 0,right := 0,counter := p 的大小

  • 定义一个数组 ans

  • 将 p 中字符的频率存储到映射 m 中

  • 对于 right := 0 到 n – 1

    • 如果 m 包含 s[right] 且 m[s[right]] 不为零,则将 m[s[right]] 减 1,将 counter 减 1,如果 counter = 0,则将 left 插入到 ans 中

    • 否则

      • 当 left < right 时,

        • 如果 s[left] 不存在于 m 中,则将 counter 加 1,并将 m[s[left]] 加 1

        • 将 left 加 1

        • 如果 m 包含 s[right] 且 m[s[right]] 不为零,则将 right 减 1,并退出循环

      • 如果 m 不包含 s[left],则设置 left := right + 1

  • 返回 ans

示例(C++)

让我们看看下面的实现来更好地理解:

 在线演示

#include <bits/stdc++.h>
using namespace std;
void print_vector(vector<auto> v){
   cout << "[";
   for(int i = 0; i<v.size(); i++){
      cout << v[i] << ", ";
   }
   cout << "]"<<endl;
}
class Solution {
public:
   vector<int> findAnagrams(string s, string p) {
      map <char, int> m;
      int n = s.size();
      int left = 0, right = 0;
      int counter = p.size();
      vector <int> ans;
      for(int i = 0; i < p.size(); i++) m[p[i]]++;
      for(int right = 0; right < n; right++){
         if(m.find(s[right]) != m.end() && m[s[right]]){
            m[s[right]]--;
            counter--;
            if(counter == 0)ans.push_back(left);
         } else {
            while(left<right){
               if(m.find(s[left]) != m.end()) {
                  counter++;
                  m[s[left]]++;
               }
               left++;
               if(m.find(s[right]) != m.end() && m[s[right]]){
                  right--;
                  break;
               }
            }
            if(m.find(s[left])==m.end())left = right + 1;
         }
      }
      return ans;
   }
};
main(){
   Solution ob;
   print_vector(ob.findAnagrams("cbaebabacd", "abc")) ;
}

输入

"cbaebabacd"
"abc"

输出

[0, 6, ]

更新于:2020-04-29

2K+ 浏览量

开启你的 职业生涯

通过完成课程获得认证

开始学习
广告