KMP板子

KMP,快速字符串匹配,其实也是一种对暴力算法的优化(但是这优化竟如此强大且著名一直沿用至今tql Orz %%%)这是板子题
这是代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cstdlib>
const int maxn=1000000+5;
using namespace std;
string s,p;
int nxtpos[maxn],lcpp[maxn],nxtpos0[maxn];//nxtpos0为未优化版nxtpos数组
void getnxt()
{
    nxtpos[0]=-1;
    nxtpos0[0]=-1;
    int len = p.length();
    int j=0,k=-1;
    while(j <= len - 1)
    {
        if(k==-1||p[j]==p[k])
        {
            j++;
            k++;
            nxtpos0[j]=k;
            if(p[j]!=p[k])
            {
                nxtpos[j] = k;
            }
            else
            {
                nxtpos[j] = nxtpos[k];
            }
        }
        else
        {
            k = nxtpos0[k];
        }
    }
}
void kmp()
{
    int i=0,j=0;
    int slen=s.length();
    int plen=p.length();
    while(i < slen)
    {
        if(j == -1||p[j] == s[i])
        {
            i++;
            j++;
        }
        else
        {
            j=nxtpos0[j];
        }
        if(j==plen)
        {
            cout<<i-j+1<<"\n";
            i=i-j+1;
            j=0;
        }
    }
}
int main()
{
    cin>>s>>p;//getline太垃圾了(不是
    getnxt();
    kmp();
    for(int i=0;i<p.length();i++)
    {
        lcpp[i]=nxtpos0[i+1];
        printf("%d ",lcpp[i]);
    }
    return 0;
}

优化的核心思想是当出现s与p失配的情况后利用nxtpos[]数组实现只移动p而不移动s上的位置指针i,所谓nxtpos数组,nxtpos[i]表示在字符串p上的位置i之前(不包括i)的字串中最大公共前缀后缀的长度(如p=ABCAB,nxtpos[4]=1,最大公共前缀后缀就是’A’。
求nxtpos的过程大概 就是个p与自己匹配的过程,个人理解,k是在完成一个不断跑前缀的任务,用来计算nxtpos[j],有一个小优化就是p[j]==p[k]的时候,由于原来的算法中k就是nxtpos[j],会导致s[i]与p[j]失配后还是会和p[k]失配,这时就继续递归使nxtpos[p]=nxtpos[k]。
然后nxtpos就求好了。
然后用nxtpos匹配,失配时j=nxtpos[j],就完了。
就完了!
经典算法tql!

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