codevs contest #1 3945 完美拓印 kmp

来源:互联网 发布:网络倾听者app如何加入 编辑:程序博客网 时间:2024/06/08 02:04

题意:链接

方法: kmp

解析:

其实是很裸的kmp

不过这道题意也好虚幻,下边界也可以,后来官方提示了但是我并没有看到,直接匹配的上边界。

于是这道题就变简单了,然而我的kmp实力写挂

一共有四种情况

第一种是上边界与大地图的下边界匹配,

第二种是上边界与大地图的上边界匹配,

第三种是下边界与大地图的上边界匹配,

第四种是下边界与大地图的下边界匹配。

其中有的情况可以运用同一套模式串。

然后讨论一下,KMP不写挂就OK

代码:

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define N 1000100using namespace std;int n,m;int a[N],b[N],ne[N],c[N],d[N];void getnext(){    int i=0,j=-1;    ne[0]=-1;    int len=n;    while(i<len)    {        if(j==-1||c[i]==c[j])        {            i++,j++;            ne[i]=j;        }else j=ne[j];    }}int kmp(){    int cnt=0;    int i=0,j=0;    getnext();    while(i<m)    {        if(j==-1||c[j]==b[i])        {            i++,j++;        }else j=ne[j];        if(j==n)        {            cnt++;            j=ne[j];        }    }    return cnt;} int ans;int main(){    scanf("%d%d",&n,&m);    for(int i=0;i<n;i++)scanf("%d",&a[i]);    for(int i=0;i<m;i++)scanf("%d",&b[i]);    if(n==1){printf("%d\n",4*m);return 0;}    n--,m--;    for(int i=0;i<n;i++)c[i]=a[i+1]-a[i];    for(int i=0;i<m;i++)b[i]=b[i+1]-b[i];    ans+=kmp();    memset(c,0,sizeof(c));    ans+=kmp();    for(int i=0;i<m/2;i++)swap(b[i],b[m-i-1]);    ans+=kmp();    for(int i=0;i<n;i++)c[i]=a[i+1]-a[i];    ans+=kmp();    printf("%d\n",ans);}
0 0