• 洛咕 P2463 [SDOI2008]Sandy的卡片


    哈希水过。

    首先这是一段delta相同的序列,按照套路差分一下,b[i]=a[i]-a[i-1],然后就是这些序列的最长公共子段

    由于数据范围很小,就可以二分,枚举第一个序列的子段然后每个子序列暴力check,跑得飞快。

    // luogu-judger-enable-o2
    #include<bits/stdc++.h>
    #define il inline
    #define vd void
    typedef long long ll;
    il int gi(){
        int x=0,f=1;
        char ch=getchar();
        while(!isdigit(ch)){
            if(ch=='-')f=-1;
            ch=getchar();
        }
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    int n,M[1001],A[1001][102];
    ll Hash1[1001][102],Base1[102],Mod1=998244853;
    ll Hash2[1001][102],Base2[102],Mod2=1000000009;
    il std::pair<ll,ll> Query(int x,int l,int r){
        return
            std::make_pair(
                (Hash1[x][r]-Hash1[x][l-1]+Mod1)*Base1[101-r]%Mod1,
                (Hash2[x][r]-Hash2[x][l-1]+Mod2)*Base2[101-r]%Mod2
            );
    }
    il bool check(int mid){
        for(int l=1;l+mid-1<=M[1];++l){
            std::pair<ll,ll>s=Query(1,l,l+mid-1);
            for(int i=2;i<=n;++i){
                bool flg=0;
                for(int j=1;j+mid-1<=M[i];++j)
                    if(Query(i,j,j+mid-1)==s)
                        {flg=1;break;}
                if(!flg)goto GG;
            }
            return 1;
          GG:;
        }
        return 0;
    }
    int main(){
    #ifndef ONLINE_JUDGE
        freopen("2463.in","r",stdin);
        freopen("2463.out","w",stdout);
    #endif
        n=gi();
        int l=0,r=1e9,mid;
        Base1[0]=1;for(int i=1;i<=101;++i)Base1[i]=Base1[i-1]*19260817%Mod1;
        Base2[0]=1;for(int i=1;i<=101;++i)Base2[i]=Base2[i-1]*23333%Mod2;
        for(int i=1;i<=n;++i){
            M[i]=gi();r=std::min(r,M[i]-1);
            for(int j=1;j<=M[i];++j)A[i][j]=gi();
            for(int j=M[i];j>1;--j)A[i][j]-=A[i][j-1];
            for(int j=1;j<=M[i];++j)Hash1[i][j]=(Hash1[i][j-1]+A[i][j]*Base1[j]%Mod1+Mod1)%Mod1;
            for(int j=1;j<=M[i];++j)Hash2[i][j]=(Hash2[i][j-1]+A[i][j]*Base2[j]%Mod2+Mod2)%Mod2;
        }
        while(l<r){
            mid=(l+r)>>1;
            if(check(mid+1))l=mid+1;
            else r=mid;
        }
        printf("%d
    ",l+1);
        return 0;
    }
    
  • 相关阅读:
    《梦断代码》读书计划
    四则运算3
    《梦断代码》读后感Ⅱ
    第二次结对开发
    首次结对开发
    四则运算2的测试
    四则运算2的任务完成时间表
    四则运算2
    《梦断代码》观后感1
    四则运算2的心路历程
  • 原文地址:https://www.cnblogs.com/xzz_233/p/9804449.html
Copyright © 2020-2023  润新知