zoukankan      html  css  js  c++  java
  • P2463 [SDOI2008]Sandy的卡片

    写一种(O(nm))的做法,也就是(O(sum 串长))的。

    先通过差分转化,把每个数变成这个数与上一个数的差,第一个数去掉,答案就是最长公共子串+1

    按照套路把所有串拼起来,中间加一个分隔符号,然后用DC3求出SA以及height

    (DC3我也不会,蒯的TJJ的板子,因为一般用倍增SA足够了)

    对每个后缀可以知道它在原来的第几个串,那么求出SA以后,答案就是一段区间([l,r]),即排名为([l,r])的这些后缀,而且必须覆盖原来的所有串,长度就是这些后缀的LCP,就是一段height的最小值

    枚举左端点,那么最小的右端点一定不小于上一个的最小右端点,所以直接维护右端点以及这一段区间包括原来每一个串的数量就好了

    最小值可以直接单调队列维护

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long lint;
    typedef unsigned long long ulint;
    namespace input
    {
        const int bufl = 1<<14;
        char buf[bufl],*s=buf,*t=buf;
        inline int fetch()
        {
            if(s==t){t=(s=buf)+fread(buf,1,bufl,stdin);if(s==t)return EOF;}
            return *s++;
        }
        inline int gi()
        {
            register int a=0,b=1,c=fetch();
            while(!isdigit(c))b^=c=='-',c=fetch();
            while(isdigit(c))a=a*10+c-48,c=fetch();
            return b?a:-a;
        }
    }
    using input::gi;
    const int N = 202007 , N3 = N*3 , maxalpha = 99999;
    int wa[N3],wb[N3],wv[N3],buc[N3];
    inline void bsort(int *s,int *a,int *b,int n,int m)
    {
        register int i;
        for(i=0;i<n;i++)wv[i]=s[a[i]];
        for(i=0;i<m;i++)buc[i]=0;
        for(i=0;i<n;i++)buc[wv[i]]++;
        for(i=1;i<m;i++)buc[i]+=buc[i-1];
        for(i=n-1;i>=0;i--)b[--buc[wv[i]]]=a[i];
    }
    inline int c0(int *s,int a,int b)
    {
        return s[a]==s[b] && s[a+1]==s[b+1] && s[a+2]==s[b+2];
    }
    inline int c12(int k,int *s,int a,int b)
    {
        if(k==2)return s[a]<s[b] || (s[a]==s[b] && c12(k-1,s,a+1,b+1));
        return s[a]<s[b] || (s[a]==s[b] && wv[a+1]<wv[b+1]);
    }
    #define f(x) ((x)/3+((x)%3==1?0:tb))
    #define g(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2)
    void dc3(int *s,int *sa,int n,int m)
    {
        int i,j,*sn=s+n,*san=sa+n,ta=0,tb=(n+1)/3,tbc=0,p;
        s[n]=s[n+1]=0;
        for(i=0;i<n;i++)if(i%3!=0)wa[tbc++]=i;
        bsort(s+2,wa,wb,tbc,m),bsort(s+1,wb,wa,tbc,m),bsort(s,wa,wb,tbc,m);
        for(sn[f(wb[0])]=0,p=1,i=1;i<tbc;i++)sn[f(wb[i])]=c0(s,wb[i-1],wb[i])?p-1:p++;
        if(p<tbc)dc3(sn,san,tbc,p);
        else for(i=0;i<tbc;i++)san[sn[i]]=i;
        for(i=0;i<tbc;i++)if(san[i]<tb)wb[ta++]=san[i]*3;
        if(n%3==1)wb[ta++]=n-1;
        bsort(s,wb,wa,ta,m);
        for(i=0;i<tbc;i++)wv[wb[i]=g(san[i])]=i;
        for(i=j=p=0;i<ta && j<tbc;p++)sa[p]=c12(wb[j]%3,s,wa[i],wb[j])?wa[i++]:wb[j++];
        for(;i<ta;p++)sa[p]=wa[i++];
        for(;j<tbc;p++)sa[p]=wb[j++];
    }
    #undef f
    #undef g
    void calheight(int *s,int *sa,int n,int *rk,int *ht)
    {
        register int i,j,k=0;
        for(i=1;i<=n;++i)rk[sa[i]]=i;
        for(i=0;i<n;ht[rk[i++]]=k)for(k?k--:0,j=sa[rk[i]-1];s[i+k]==s[j+k] && k<n;++k);
        return;
    }
    char s[N3];
    int n,ss[N3],sa[N3],rk[N3],ht[N3];
    int p[N3],S[N3];
    int que[N3],hd,tl,cnt[N3];
    int main()
    {
        int NN=gi(),n=0,sep=0;
        if(NN==1)return printf("%d
    ",gi()),0;
        while(NN--){
            int t=gi(),lst=gi();
            while(--t){
                int x=gi();
                S[n++]=lst-x+10000;
                lst=x;
            }
            S[n++]=++sep;
        }
        s[n]=0;
        dc3(S,sa,n+1,20000);
        calheight(S,sa,n,rk,ht);
        int k=1;
        for(int i=0;i<n;++i)if(S[i]>1000)p[i]=k;else ++k;//p[i]是后缀i属于原来的第几个串
        int CNT=0,r=k,Mx=0;//cnt是原来每个串的出现次数,CNT是总的
        hd=tl=0;
        --k;
        for(int i=k+1;i<=n;++i){
            while(r<=n&&CNT<k){
                if(cnt[p[sa[r]]]++==0)++CNT;
                if(r){
                    while((hd^tl)&&ht[que[tl-1]]>ht[r])--tl;
                    que[tl++]=r;
                }
                ++r;
            }
            if(CNT<k)break;
            while((hd^tl)&&que[hd]<=i)++hd;
            if(hd^tl)Mx=std::max(Mx,ht[que[hd]]);
            if(--cnt[p[sa[i]]]==0)--CNT;
        }
        printf("%d
    ",Mx+1);
        return 0;
    }
    

    (大括号换行的是蒯的板子,不换行的也就是核心代码是我自己写的,DC3只是为了保证复杂度而已)

  • 相关阅读:
    深入MySQL(一):MySQL的组织架构
    使用graalvm nativeimage 快速暴露jar 代码为native 共享库
    SQL注入__布尔盲注和时间盲注 菜鸟
    linux网络配置,无法解析或者打开软件包列表
    django入门视图
    三.面试题
    select,poll,epoll的区别以及使用方法
    Linux从入门到入坑
    品味Spring Cache设计之美
    JAVA_基础篇(1)_JDK 8 的下载、安装与配置
  • 原文地址:https://www.cnblogs.com/xzz_233/p/10072103.html
Copyright © 2011-2022 走看看