[KMP模板题]HDU-1711 Number Sequence

传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1711

题意:裸的模式匹配问题,N值较大,必须使用线性算法,考虑上KMP。

关于KMP:

好久之前就看过KMP不过一直没搞懂,最近要搞下字符串,所以先拿它开刀,翻看了严蔚敏老师的数据结构,研究了许久,算是对KMP略知一二了吧,其KMP主算法还是比较好理解来的(不回溯主串匹配指针,当失配时,利用已经匹配的部分串的信息,使模式串指针向前移动,然后继续匹配),关键在于NEXT数组的求法,其实也不算很难理解(一个递推关系+自匹配的过程),书上后面说的那个修正NEXT数组的求法也比较好理解(当P[i]=P[Next[i]]时,此次滑动的没有作用的,所以直接滑到下一次去)。

关于算法的云云就没什么好说的,严蔚敏老师的书说的十分详细。(其实也是自己理解还不够深刻,不能很好的表达出来)

还有要注意一些关于coding方面的技巧。

献上一个使用了修正NEXT数组的KMP模板:

#include<iostream>
using namespace std;
const int MAXN = 1111111,MAXM = 11111;
int T[MAXN],P[MAXM],Next[MAXM];
void MakeNext(int M){
    Next[0] = -1;
    int i = 0, j = -1;
    while(i<M){
        if(j==-1||P[i]==P[j]){
            i++,j++;
            if(P[i]!=P[j])Next[i] = j;
            else Next[i] = Next[j];
        }
        else j = Next[j];
    }
}
int KMP(int N,int M){
    int i=0,j=0;
    while(i<N&&j<M){
        if(T[i]==P[j]||j==-1)i++,j++;
        else j = Next[j];
    }
    if(j==M)return i-M+1;
    else return -1;
}
int main(){
    int N,M,C;
    scanf("%d",&C);
    while(C--){
        scanf("%d%d",&N,&M);
        for(int i=0;i<N;i++)scanf("%d",&T[i]);
        for(int i=0;i<M;i++)scanf("%d",&P[i]);
        if(M>N)printf("-1\n");
        else{
            MakeNext(M);
            printf("%d\n",KMP(N,M));
        }
    }
    return 0;
}


你可能感兴趣的:(sequence)