题解:

后缀数组

对所有序列差分一下

公共串的长度+1就是答案了

二分 扫一遍height即可,..

代码:

#include <bits/stdc++.h>
using namespace std;
const int N=1005,M=1000005;
int n,mn=2e9,mx=0,lt,rt=2e9,mid,ans=1,a[N][N],l[N],b[M],id[M];
int tot,vis[N],cnt,sa[M],ta[M],rk[M],ht[M],wa[M],wb[M],ca[M],cb[M];
int check(int k)
{
      for (int i=1;i<=tot;i++)
        {
        if (ht[i]<k)
         {
             memset(vis,0,sizeof(vis));
            cnt=0;
         }
        if (!vis[id[sa[i]]])vis[id[sa[i]]]=1,++cnt;
        if (cnt==n)return 1;
       }
      return 0;
}
int main()
{
      scanf("%d",&n);
      for (int i=1;i<=n;i++)
     {
        scanf("%d",l[i]);
        for (int j=1;j<=l[i];j++)
         {
              scanf("%d",&a[i][j]);
              if (j>1)mx=max(mx,a[i][j]-a[i][j-1]);
         }
        rt=min(rt,l[i]);
       }
      for (int i=1;i<=n;i++)
        {
        for (int j=2;j<=l[i];j++)
         {
             b[++tot]=a[i][j]-a[i][j-1];
            id[tot]=i;
         }
        b[++tot]=++mx;
       }
      for (int i=1;i<=tot;i++)mn=min(mn,b[i]);
      for (int i=1;i<=tot;i++)b[i]=b[i]-mn+1,mx=max(mx,b[i]);
      memset(ca,0,sizeof(ca));
      for (int i=1;i<=tot;i++)ca[b[i]]++;
      for (int i=1;i<=mx;i++)ca[i]+=ca[i-1];
      for (int i=tot;i>=1;i--)sa[ca[b[i]]--]=i;
      rk[sa[1]]=1;
      for (int i=2;i<=tot;i++)rk[sa[i]]=rk[sa[i-1]]+(b[sa[i]]!=b[sa[i-1]]);
      for (int k=1;rk[sa[tot]]<tot;k<<=1)
       {
        memset(ca,0,sizeof(ca));
        memset(cb,0,sizeof(cb));
        for (int i=1;i<=tot;i++)
         {
             ca[wa[i]=rk[i]]++;
            cb[wb[i]=i+k<=tot?rk[i+k]:0]++;
         }
        for (int i=1;i<=tot;i++)
         {
             ca[i]+=ca[i-1];
            cb[i]+=cb[i-1];
         }
        for (int i=tot;i;i--)ta[cb[wb[i]]--]=i;
        for (int i=tot;i;i--)sa[ca[wa[ta[i]]]--]=ta[i];
        rk[sa[1]]=1;
        for (int i=2;i<=tot;i++)
         rk[sa[i]]=rk[sa[i-1]]+(wa[sa[i]]!=wa[sa[i-1]]||wb[sa[i]]!=wb[sa[i-1]]);
       }
      for (int i=1,j=0;i<=tot;i++)
       {
        if (j)j--;
        while (b[i+j]==b[sa[rk[i]-1]+j])j++;
        ht[rk[i]]=j;
       }
      while (lt<=rt)
       {
        if (check(mid=(lt+rt)>>1))ans=mid+1,lt=mid+1;
        else rt=mid-1;
       }
      printf("%d\n",ans);
}

 

posted on 2018-03-05 18:57  宣毅鸣  阅读(105)  评论(0编辑  收藏  举报