KMP小结

之前刷了KMP专题,后来发现全忘了。比赛的时候连kmp怎么写都忘了。(算法学了就忘,真想打死自己)所以就来写写博客,整理一下,顺便回想一下。
大概会分三四篇来写,写下基本的kmp,然后kmp的应用, Manacher,还有最大最小表示法。至于扩展kmp,感觉kmp还是可以解决的(一点拙见), 就没学。

基本kmp

Code:

#include <bits/stdc++.h>
using namespace std;

const int maxn = 1e6 + 10;
char str1[maxn], str2[maxn];
int Next[maxn];

void get_Next()
{
    int i, j, m = strlen(str2);
    Next[0] = 0;
    for(i = 1; i < m; i++)
    {
        j = Next[i - 1];
        while(j > 0 && str2[i] != str2[j])
        {
            j = Next[j - 1];
        }
        if(str2[i] == str2[j])
            Next[i] = j + 1;
        else
            Next[i] = 0;
    }
}


int kmp()
{
    int len1 = strlen(str1), len2 = strlen(str2);
    int i, j, ans = 0;
    for(i = 0, j = 0; i < len1; i++)
    {

        while(j > 0 && str1[i] != str2[j])
        {
            j = Next[j - 1];
        }
        if(str1[i] == str2[j])
            j++;
        if(j == len2)
        {
            ans++;
            j = Next[j - 1];//可重复的 比如 AZA
                            //            AZAZAZA 输出3
           // j = 0;                      输出2 不可重复

        }
    }
    return ans;
}

int main()
{
    int t;
    scanf("%d", &t);
    while(t--)
    {
        scanf("%s %s", str2, str1);
        get_Next();
        int v = kmp();
        printf("%d\n", v);
    }

}

自我感觉kmp真的很神奇,Next[i - 1] = x记录的是说第i个字符前x有个字符和前缀长度为x的匹配,这也就是为什么Next数组可以用来表示前后缀的匹配程度的原因了。
当进行匹配时,如果当前第x个不匹配了,就说明前x个已经是匹配的了。举个栗子,ababababc和ababc的匹配,ababc的Next是00120, 当c个第五个a不匹配了,就说明他们前四个是匹配的,这时Next[3]=2,说明ab和前缀ab是一样的,既然34位置上的ab可以和母串ab匹配,前缀的ab自然就可以,这样直接去比较abab*a*babc和abab*c* 就好啦,省了很多时间。本来kmp就是不想浪费之前已经匹配过的信息才加以优化的。

猜你喜欢

转载自blog.csdn.net/deerly_/article/details/78868208
kmp
今日推荐