KMP算法

文章目录

  • KMP思路简介
  • KMP组成
  • CODE
  • 代码思路
  • 参考题解



KMP思路简介

对于一长段字符串和一个模版串,我们想查找字符串是否包含模版串,通常方法是暴力枚举每个字符。 K M P KMP KMP 在暴力基础上优化,如果模版串的前后缀相同,那么直接将模版串移过来再继续往后匹配。
KMP算法_第1张图片


KMP组成

  1. next[]数组:我们需要预处理一个用来记录与前缀最大重合长度的数组。
  2. 匹配过程:将字符串与模版串匹配。

CODE

板子题:这儿。

#include 
#include 
#include 

using namespace std;

int n, m;
const int N = 1e5 + 10, M = 1e6 + 10;
char p[N], s[M];
int ne[M];

int main()
{
    cin >> n;
    scanf("%s", p + 1);
    cin >> m;
    scanf("%s", s + 1);
    
    for(int i = 2, j = 0; i <= n; ++i){
        while(j && p[i] != p[j + 1]) j = ne[j];
        if(p[i] == p[j + 1]) j++;
        ne[i] = j;
    }
    
    for(int i = 1, j = 0; i <= m; ++i){
        while(j && s[i] != p[j + 1]) j = ne[j];
        if(s[i] == p[j + 1]) j++;
        if(j == n){
            printf("%d ", i - n);
            j = ne[j];
        }
    }
}

代码思路

  1. 我们将两个字符串从下标 1 1 1 开始读入(从 0 0 0 也行,不过麻烦一点,我还没想明白 <_>)。

  2. 预处理next[]数组:

    • 只要下一位没匹配上而且j还没缩回原点就往前捯,从前缀位置往后匹配。

    • 如果说后一位匹配了,那么将后缀拉到这一位上。

    • 原数组中的后缀元素i对应的前缀就是j

      图解:KMP算法_第2张图片
      由此图我们可以发现,其实i是后缀的指针,而j是前缀的指针。

  3. 匹配模版串(思路与next相同):

    • 只要j没缩回原点就往后一位匹配,如果匹配不成功就往前缀找。
    • 如果后一位匹配成功,我们匹配成功的长度 + 1 + 1 +1
    • 如果匹配成功(长度与模版串一致),输出,然后找下一个:回到前缀处,继续往后匹配。

参考题解

题解1

你可能感兴趣的:(算法学习记录,算法,c++,笔记)