• [SDOI2008][luogu2463] Sandy的卡片 [kmp]


    题面

    传送门

    思路

    这道题里面有三个主要问题:

    1.由“数值相等”变成了“加上一个整数以后数值相等”(减去等价于加负数)

    2.由“最多匹配多少位(从第一位开始)”变成了从“任意一位开始匹配”

    3.由“单文本串”变成了“多文本串”,而且是文本串内部自己匹配

    我们按照难度顺序(3-1-2)来依次解决他们

    问题三:多文本串

    这个问题是最简单的,因为每个串长度不超过100,最多1000个串

    所以,我们搞一个串出来成为模式串,然后用它去匹配剩下的串,结果取min就行了

    问题一:数值加上整数相等

    这个问题中我们要贯彻一个思想:取不变量

    考虑一个序列,当它的每一个元素都增加了一定值以后,什么还是不变的?

    没错,相邻元素(或者说任意两个元素)的差值

    所以,本题中,我们只要把原来的序列变成长度小了1,元素为原来序列相邻两位之差的新序列来跑匹配,最后把答案加一就好了

    问题二:可以从每一位开始匹配

    这个问题,在解决了问题三以后也能迎刃而解:数据范围实在是太!小!了!

    我们完全可以枚举模式串的开始位置,求出next数组,然后对于剩下的串每一个匹配一下,还能腾出一半的运行时间,大声喊出:

    “zcy吊打集训队!”

    Code:

    // luogu-judger-enable-o2
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    #define inf 1e9
    using namespace std;
    inline int read(){
        int re=0,flag=1;char ch=getchar();
        while(ch>'9'||ch<'0'){
            if(ch=='-') flag=-1;
            ch=getchar();
        }
        while(ch>='0'&&ch<='9') re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
        return re*flag;
    }
    int a[1010][110],b[110];int N,n,m[1010],fail[110],ans=0,tans=inf,tmp;
    int main(){
        N=read();int i,j,t1,t2,k,l;
        n=read();t1=read();for(i=0;i<n-1;i++) t2=read(),b[i]=t2-t1,t1=t2;
        b[n-1]=b[n]=b[n+1]=-inf;
        for(j=1;j<N;j++){
            m[j]=read();t1=read();
            for(i=0;i<m[j]-1;i++) t2=read(),a[j][i]=t2-t1,t1=t2;
            a[j][m[j]-1]=a[j][m[j]]=inf;
        }
        for(k=n-1;k>=1;k--){
            memset(fail,0,sizeof(fail));
            j=0;tans=inf;
            for(i=1;i<k;i++){
                while(j&&(b[i]!=b[j])) j=fail[j];
                j+=(b[i]==b[j]);fail[i+1]=j;
            }
            for(l=1;l<N;l++){
                j=0;tmp=0;
                for(i=0;i<m[l]-1;i++){
                    while(j&&a[l][i]!=b[j]) j=fail[j];
                    j+=(a[l][i]==b[j]);
                    tmp=max(tmp,j);
                    if(j==k) break;
                }
                tans=min(tans,tmp);
            }
            for(i=0;i<k-1;i++) b[i]=b[i+1];b[k]=-inf;
            ans=max(ans,tans);
        }
        printf("%d",ans+1);
    }
    
  • 相关阅读:
    石头的用途
    [转] Analysis: Khronos and OpenGL ARB merge
    ★○值得你我珍藏一世的80句话○★
    PasswordStrength 控件
    NumericUpDownExtender 控件
    ReorderList控件
    Nobot控件拒绝机器人行为
    PopupControlExtender控件
    PagingBulletedList 控件学习
    MutuallyExlcusiveCheckBox控件
  • 原文地址:https://www.cnblogs.com/dedicatus545/p/8900736.html
Copyright © 2020-2023  润新知