hdu1711 kmp

来源:互联网 发布:java hdfs jar包 编辑:程序博客网 时间:2024/05/10 00:18

把O(N*M)立减到O(N+M)的匹配算法,有没有好厉害的样子!结果next数组什么的,看的时候简直醉了。。

鉴于1711纯裸,那就借这个说说~也不知道自己到底有木有懂==


题意即给出两串数字,暂叫他a串和b串吧~要求输出b串与a串开始匹配的位置

比如那个样例

1 2 1 2 312 3 1 3 2 1 2

1 2 3 1 3

从第6位开始,所以输出6

当然很简单呀,两个循环一位一位比下去不就得了?

看这范围1 <= M <= 10000, 1 <= N <= 1000000,Time Limit: 10000/5000 MS (Java/Others),还敢暴力吗?


kmp基本思想就是把用不着重复比较的部分跳过去

bf的第二轮:

1 2 1 2 31 2 3 1 3 2 1 2

1 2 3 1 3

kmp的第二轮:

1 2 1 2 31 2 3 1 3 2 1 2

1 2 3 1 3

嗯,其实那个2完全可以直接跳过是把~

所以感觉kmp就是找出应该跳过哪一些,这就是通过next数组实现的~

void getnext(int *b,int *next){    next[0]=next[1]=0;    for(int i=1;i<M;i++)    {        int j=next[i];        while(j&&b[i]!=b[j])            j=next[j];        next[i+1]=(b[i]==b[j]?j+1:0);    }}

这个next其实相当于在比较之前就已经初始化好了,计算嘛,是根据什么前缀后缀是否一样来的,详细解释篇幅会很多诶,反正网上资料很多哒~

嗯,next初始化好了,就要开始比较了,如何机智的避开不需要比较的那些元素呢?

int kmp(int *a,int *b,int *next){    getnext(b,next);    int j=0;    for(int i=0;i<N;i++)    {        while(j&&a[i]!=b[j])            j=next[j];        if(a[i]==b[j])            j++;        if(j==M)        {            return i+1-M+1;        }    }    return -1;}

i,j还是俩指针,跳着指

嗯,就是这样,鉴于标题,再发个1711的主函数~

int main(){    int T;    int po;    scanf("%d",&T);    while(T--)    {        memset(a,0,sizeof(a));        memset(b,0,sizeof(b));        memset(next,0,sizeof(next));        scanf("%d%d",&N,&M);        //if(N<M){printf("-1\n");continue;}        for(int i=0;i<N;i++)            scanf("%d",&a[i]);        for(int j=0;j<M;j++)            scanf("%d",&b[j]);        po=kmp(a,b,next);        printf("%d\n",po);    }    return 0;}






0 0
原创粉丝点击