KMP算法--字符串匹配

kmp算法简介

KMP算法一种改进的模式匹配算法,是D.E.Knuth、V.R.Pratt、J.H.Morris于1977年联合发表,KMP算法又称克努特-莫里斯-普拉特操作。它的改进在于:每当从某个起始位置开始一趟比较后,在匹配过程中出现失配,不回溯i,而是利用已经得到的部分匹配结果,将一种假想的位置定位“指针”在模式上向右滑动尽可能远的一段距离到某个位置后,继续按规则进行下一次的比较。

next数组的含义

KMP的关键在于next数组。

next数组的含义为以i为终点的最长的相同前后缀。

举个例子:

ababa

i=1时,字符串为a,next[1] = 0;

i=2时,字符串为ab,next[2] = 0;

i=3时,字符串为aba

    前缀为a、ab

    后缀为a、ba

    最长相同为a,长度为1

    故next[3] = 1;

i=4时,字符串为abab

    前缀为a、ab、aba

    后缀为b、ab、bab

    最长相同为ab,长度为2

    故next[4] = 2;

i=5时,字符串为ababa

    前缀为a、ab、aba、abab

    后缀为a、ba、aba、baba

    最长相同为aba,长度为3    故next[5] = 3;

next数组为模式串匹配失败后,可以利用的失败信息,即向前移动多少位。

kmp模版

模版默认从1开始,这样比较简洁。

#include <iostream>

using namespace std;

const int N = 100010, M = 1000010;

int n, m;
int ne[N];
char s[M], p[N];

int main()
{
    cin >> n >> p + 1 >> m >> 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];
        }
    }
    return 0;
}

 

posted @ 2021-02-14 12:58  zju_cxl  阅读(54)  评论(0编辑  收藏  举报