完美拓印(kmp模板)

完美拓印

题目描述:
小Q获得了一个神奇的印章,这个印章宽n个单位长度,印章的其中三个棱都是直的,而另外一个方向上,对于每个单位宽度的部分,是一样直的,并且与反方向的棱*行,如下图所示。
小Q的印章上有一个不关于中心对称的图形(不一定是上图的Qrz),他现在要在一张地图上拓上印,地图上有一段个m单位长度、*似水*的边界线,但是放大到单位长度时还是有一定的高低差异,但对于单位宽度的部分,是一样直的,与水*轴线垂直,如下图所示。
这里写图片描述
小Q希望自己的印章一边的边缘能恰好地与边界线重合(不能部分重合、不能越过边界线),他现在只可以将印章旋转180度或者不旋转(这样印章可能存在有两边可以与边界线重合的情况),然后*移到适当的位置,问小Q有多少种可行的方案,两种方案不同被定义为两种方案用印章印出的图案互不重合。
输入描述:
第一行两个正整数n和m,表示印章的宽度和截取边界线的长度。
第二行n个正整数,表示印章从左到右每个单位宽度对应的两条*行线之间的距离。
第三行m个整数,表示所截取边界线从左到右每个单位宽度对应的竖直方向上的坐标。
输出描述:
一个整数,表示可行方案的种类数。
样例输入:
5 12
3 4 4 3 2
2 4 5 5 4 3 2 2 3 3 2 1
样例输出:
3
数据范围及提示:
对于30%的数据,有n*m≤2*107。
对于60%的数据,有n,m≤105。
对于100%的数据,有n,m≤106,所有数字的绝对值不超过10^9。
思路:
题意是说给定两条曲线,一条是*整的,另外一条的起伏给出,再给出一条长曲线,让我们找出在长曲线中有多少个短曲线。
很明显是KMP问题,将输入的曲线起伏和长曲线转化为差分数组,直接匹配即可,但是这题坑在印章底部也是可以放的,也就是要多加一条*整曲线进行匹配

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int Maxn=1000010;
int n,m;
int arr[Maxn],q[Maxn];
int s[Maxn],p[Maxn];
int z[Maxn];
int next[Maxn];
int ans;
int KMP(int *s,int *p)
{
    int j=-1;
    int res=0;
    for (int i=0;i<m;i++)
    {
        while(j>-1&&s[i]!=p[j+1])
        j=next[j];
        if (s[i]==p[j+1])
            j++;
        if (j==n-1)
        {
            res++;
            j=next[j];
        }
    }
    return res;
}
void getnext(int *arr)
{
    next[0]=-1;
    int j=-1;
    for(int i=1;i<n;i++)
    {
        while(j>-1&&arr[i]!=arr[j+1])
        j=next[j];
        if(arr[i]==arr[j+1])
        j++;
        next[i]=j;
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    if(n==1)
    {
        printf("%d
",m*4);
        return 0;
    }
    for(int i=0;i<n;i++)
    scanf("%d",&arr[i]);
    for(int i=0;i<m;i++)
    scanf("%d",&q[i]);
    n--,m--;
    for(int i=0;i<n;i++)
    p[i]=arr[i]-arr[i+1];
    for(int i=0;i<m;i++)
    s[i]=q[i]-q[i+1];
    getnext(p);
    ans+=KMP(s,p);
    int cnt=0;
    for(int i=n;i>=1;i--)
    p[cnt++]=arr[i-1]-arr[i];
    getnext(p);
    ans+=KMP(s,p);
    getnext(z);
    ans+=KMP(s,z)*2;
    printf("%d
",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/cax1165/p/6070927.html