• 4698: Sdoi2008 Sandy的卡片


    前言

    总之这个东西说起来很麻烦就是了,

    思路

    差分合并+后缀数组+二分(dddl)
    类似于那个bzoj1031的复制子串和那个poj1743的差分
    来看个例子

    3
    5 1 2 3 4 5
    4 1 1 1 2  
    4 1 2 3 4
    

    变成了这个(最后一个INF最好删掉吧,应该不影响的吧)

    1111 INF 001 INF 111
    1.   001 INF 111             belong[2] 0
    2.   01 INF 111              belong[2] 1
    3.   1                       belong[3] 0
    4.   11                      belong[3] 1
    5.   111                     belong[3] 2
    6.   1111 INF 001 INF 111    belong[1] 3
    7.   111 INF 001 INF 111     belong[1] 3
    8.   11 INF 001 INF 111      belong[1] 2
    9.   1 INF 001 INF 111       belong[1] 1
    10.  1 INF 111               belong[2] 2
    11.  INF 111                 belong[0] 0
    12.  INF 001 INF 111         belong[0] 1
    

    很明显,答案是min[5,10]+1=1+1=2
    belong是后缀i属于那一部分本串(上来给你的哪一行)
    INF属于belong【0】
    就是height数组包含着所以belong的最小值得最大值
    很容易想到二分
    可我想dddl来着,没弄出来
    就直接暴力的st表+指针移动了nlogn
    好像是他俩都没用

    错误

    写了半天dddl没写出来,吐血啦
    看来dddl还是硬伤,找时间填坑

    代码

    #include <bits/stdc++.h>
    #define FOR(i,a,b) for(int i=a;i<=b;++i)
    #define ROF(i,a,b) for(int i=a;i>=b;--i)
    using namespace std;
    const int maxn=4e5+8;
    int read() {
        int x=0,f=1;char s=getchar();
        for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1;
        for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0';
        return x*f;
    }
    int nn,n,m;
    int s[maxn],tmp[1401];
    int len[1010];
    int sa[maxn],rk[maxn],c[maxn],x[maxn];
    void get_sa() {
        FOR(i,1,n) ++c[rk[i]=s[i]];
        FOR(i,1,m) c[i]+=c[i-1];
        ROF(i,n,1) sa[c[rk[i]]--]=i;
        for(int k=1;k<=n;k<<=1) {
            int p=0;
            FOR(i,n-k+1,n) x[++p]=i;
            FOR(i,1,n) if(sa[i]>k) x[++p]=sa[i]-k;
            FOR(i,1,m) c[i]=0;
            FOR(i,1,n) ++c[rk[i]];
            FOR(i,1,m) c[i]+=c[i-1];
            ROF(i,n,1) sa[c[rk[x[i]]]--]=x[i],x[i]=0;
            swap(rk,x);
            rk[sa[1]]=1,p=1;
            FOR(i,2,n) rk[sa[i]]=(x[sa[i]]==x[sa[i-1]]&&x[sa[i]+k]==x[sa[i-1]+k]) ? p : ++p;
            if(p==n) break;
            m=p;
        }
    }
    int height[maxn],st[maxn][21];
    void get_height() {
        FOR(i,1,n) rk[sa[i]]=i;
        int k=0;
        FOR(i,1,n) {
            k=k?k-1:0;
            int j=sa[rk[i]-1];
            while(s[i+k]==s[j+k]&&i+k<=n&&j+k<=n) k++;
            height[rk[i]]=k;
        }
        height[0]=0;
        FOR(i,1,n) st[i][0]=height[i];
        FOR(j,1,20) 
        for(int i=1;i+(1<<j)-1<=n;++i)
        st[i][j]=min(st[i][j-1],st[i+(1<<(j-1))][j-1]);
    }
    int LCP(int i,int j) {
        int x=log2(j-i+1);
        return min(st[i][x],st[j-(1<<x)+1][x]);
    }
    int belong[maxn],tong[maxn];
    int main() {
        nn=read(),m=2001;
        FOR(i,1,nn) {
            len[i]=read();
            FOR(j,1,len[i]) tmp[j]=read();
            FOR(j,1,len[i]-1) s[++n]=tmp[j+1]-tmp[j],belong[n]=i;
            s[++n]=2001;
        }
        n--;
        get_sa();
        get_height();
        int OU_MY_FFF=0;
        int l=1,js=0;   
        FOR(i,1,n) {
            if(tong[belong[ sa[i] ]]==0 && belong[sa[i]]) js++;
            tong[belong[ sa[i] ]]++;
            while(tong[belong[sa[l]]]>1&&l<=i) tong[belong[sa[l]]]--,l++;
            while(belong[sa[l]]==0) l++;
            if(js==nn) OU_MY_FFF=max(OU_MY_FFF,LCP(l+1,i));
        }
        cout<<OU_MY_FFF+1<<"
    ";
        return 0;
    }
    
  • 相关阅读:
    /bin/bash^M:损坏的解释器: 没有那个文件或目录
    QT槽函数处理线程
    Strategy策略模式
    Proxy代理模式
    Ubuntu系统修改BIOS时间问题
    Ubuntu下安装Goldendict(翻译软件)
    自定义QMenu
    C connect实现Timeout效果(Windows)
    059 Python计算生态概览
    058 程序设计方法学小结
  • 原文地址:https://www.cnblogs.com/dsrdsr/p/10152531.html
Copyright © 2020-2023  润新知