「SDOI2008」Sandy 的卡片

用第一个串建立后缀自动机。然后别的串在上面跑。从根节点开始。如果当前不能转移,一直移到slink或者根。如果移到根,能匹配长度变为0,否则变为maxlen[能转移的点]+1,再转移。转移完往slink上跑,它们至少都能匹配maxlen,和当前匹配取最小。注意在任何点上匹配长度不超过它能表示的最大长度。

//#pragma comment(linker,"/STACK:1024000000,1024000000")
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <iomanip>
#include <cstring>
#include <map>
#include <queue>
#include <set>
#include <cassert>
#include <stack>
#include <bitset>
#include <fstream>
#define mkp make_pair
using namespace std;
const double EPS=1e-8;
typedef long long lon;
const lon SZ=1107,INF=0x7FFFFFFF,mod=1000000007;
int cnt,trans[SZ][2010],slink[SZ],maxlen[SZ];
int minlen[SZ],n,arr[SZ],ans[SZ];
//sadcsadsadasdasdsadsadasdasdsadasd
//aabba

int add(int pre,int cur)
{
    int z=++cnt;
    int u=pre;
    for(;u!=-1&&!trans[u][cur];u=slink[u])
    {
        trans[u][cur]=z;
    }
    if(u==-1)
    {
        //cout<<"kind: "<<1<<endl;
        maxlen[z]=maxlen[pre]+1;
        minlen[z]=1;
        slink[z]=0;
    }
    else
    {
        int x=trans[u][cur];
        //if(pre==8)cout<<pre<<"here"<<x<<endl;
        if(maxlen[x]==maxlen[u]+1)
        {
            maxlen[z]=maxlen[pre]+1;
            minlen[z]=maxlen[x]+1;
            slink[z]=x;
        }
        else
        {
            int y=++cnt;
            memcpy(trans[y],trans[x],sizeof(trans[x]));
            maxlen[y]=maxlen[u]+1;
            minlen[y]=maxlen[slink[x]]+1;
            slink[y]=slink[x];
            maxlen[x]=maxlen[x];
            minlen[x]=maxlen[y]+1;
            slink[x]=y;
            maxlen[z]=maxlen[pre]+1;
            minlen[z]=maxlen[y]+1;
            slink[z]=y;
            for(;u!=-1&&trans[u][cur]==x;u=slink[u])
            {
                trans[u][cur]=y;
            }
        }
    }
    return z;
}

int maxv[SZ],tmp[SZ];
bool vst[SZ];

void init()
{
    cin>>n;
    for(int i=0;i<n;++i)
    {
        int sz;
        cin>>sz;
        for(int i=1;i<=sz;++i)cin>>arr[i];
        for(int i=sz;i>=1;--i)arr[i]-=arr[i-1]-1000;
        if(i==0)
        {
            int pre=0;
            memset(slink,-1,sizeof(slink));
            for(int i=2;i<=sz;++i)
            {
                pre=add(pre,arr[i]);
            }
            for(int i=1;i<=cnt;++i)maxv[i]=INF;
        }
        else
        {
            memset(vst,0,sizeof(vst));
            memset(tmp,0,sizeof(tmp));
            int u=0,it=0;
            for(int i=2;i<=sz;++i)
            {
                int cur=arr[i];
                for(;u!=-1&&trans[u][cur]==0;u=slink[u]);
                if(u==-1)
                {
                    u=0;
                    it=0;
                }
                else
                {
                    it=min(it,maxlen[u]);
                    u=trans[u][cur];
                    ++it;
                    tmp[u]=max(tmp[u],it);
                    if(!vst[u])++ans[u];    
                    //cout<<"u: "<<u<<" "<<tmp[u]<<endl;
                    vst[u]=1;
                    int w=slink[u];
                    for(;w!=-1;w=slink[w])
                    {
                        if(!vst[w])++ans[w],vst[w]=1;
                        tmp[w]=max(tmp[w],min(it,maxlen[w]));
                    }
                }
            }
            for(int i=1;i<=cnt;++i)
            {
                //cout<<"tmp[i]: "<<tmp[i]<<endl;
                maxv[i]=min(maxv[i],tmp[i]);
            }
        }
    }
    int res=0;
    for(int i=1;i<=cnt;++i)
    {
        //cout<<"i: "<<i<<" "<<ans[i]<<" "<<maxv[i]<<endl;
        if(ans[i]==n-1&&maxv[i]!=INF)
        {
            res=max(res,maxv[i]);
        }
    }
    cout<<res+1<<endl;
}

void work()
{
    
}

int main()
{    
    //std::ios::sync_with_stdio(0);
    //freopen("d:\\1.txt","r",stdin);
    lon casenum;
    //cin>>casenum;
    //cout<<casenum<<endl;
    //for(lon time=1;time<=casenum;++time)
    //for(lon time=1;cin>>n,n;++time)
    {
        init();
        work();
    }
    return 0;
}
/*
3
5 0 0 1 1 1
5 1 0 0 1 1
5 1 0 1 1 1

5
5 1 1 1 1 1
5 1 1 1 1 1
5 1 1 1 1 1
5 1 1 1 1 1
5 1 1 1 1 1

3
8 0 0 1 1 0 0 1 1
8 0 1 1 0 1 0 1 1
8 1 1 1 1 1 0 1 1



3
6 0 0 1 1 0 0
6 0 1 1 0 1 0
6 1 1 1 1 1 0

3
5 0 1 1 0 0
5 1 1 0 1 0
5 1 1 1 1 0

3
4 1 1 0 0
4 1 0 1 0
4 1 1 1 0


3
4 1 1 0 0
4 1 1 1 1
4 1 1 0 1
*/

猜你喜欢

转载自www.cnblogs.com/gaudar/p/10201403.html