• 完美拓印(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;
    }
  • 相关阅读:
    《人件》读书笔记3
    《人件》读书笔记2
    《人件》读书笔记1
    《编程珠玑》读书笔记3
    《编程珠玑》读书笔记2
    学习进度报告2021/4/10
    《编程珠玑》读书笔记1
    学习进度报告2021/4/9
    学习进度报告2021/4/8
    关于软件体系架构质量属性的科技小论文
  • 原文地址:https://www.cnblogs.com/cax1165/p/6070927.html
Copyright © 2020-2023  润新知