BZOJ4698 Sdoi2008 Sandy的卡片
传送门
转化题意可以得到 我们求得就是 所有串的差分串的LCS
SAM水过就好啦
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<map>
#define inf 20021225
#define ll long long
#define mxn 110
using namespace std;
struct edge{int to,lt;}e[mxn*4]; int in[mxn*4],cnt;
struct node{int fa,len;map<int,int> mp;}t[mxn*4];
int poi,rt,lt,ch[mxn],n;
int mx[mxn*4],mn[mxn*4];
void add(int x,int y)
{
e[++cnt].to=y;e[cnt].lt=in[x];in[x]=cnt;
}
void pre(){rt=lt=++poi;memset(mn,48,sizeof(mn));}
void insert(int c)
{
int p=lt, np=lt=++poi; t[np].len=t[p].len+1;
for(;p&&!t[p].mp[c];p=t[p].fa) t[p].mp[c]=np;
if(!p){t[np].fa=rt; return;}
int q=t[p].mp[c];
if(t[q].len==t[p].len+1){t[np].fa=q;return;}
int nq=++poi; t[nq].mp=t[q].mp; t[nq].len=t[p].len+1;
t[nq].fa=t[q].fa; t[np].fa=t[q].fa=nq;
for(;p&&t[p].mp[c]==q;p=t[p].fa) t[p].mp[c]=nq;
}
void build(){for(int i=2;i<=poi;i++) add(t[i].fa,i);}
void init(){memset(mx,0,sizeof(mx));}
void find()
{
int pos=rt,len=0;
for(int i=1;i<=n;i++)
{
int tmp=ch[i];
if(t[pos].mp[tmp]) pos=t[pos].mp[tmp],len++;
else
{
for(;pos&&!t[pos].mp[tmp];pos=t[pos].fa);
if(!pos) pos=rt,len=0;
else len=t[pos].len+1,pos=t[pos].mp[tmp];
}
//printf("%d\n",len);
mx[pos]=max(mx[pos],len);
}
}
void dfs(int x)
{
for(int i=in[x];i;i=e[i].lt)
{
dfs(e[i].to);
mx[x]=max(mx[x],min(mx[e[i].to],t[x].len));
}
mn[x]=min(mn[x],mx[x]);
}
int a[mxn];
int main()
{
int T;
scanf("%d",&T);
for(int i=1;i<=T;i++)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
if(i>1) ch[i-1]=a[i]-a[i-1];
}
n--;
if(i==1)
{
pre();
for(int i=1;i<=n;i++) insert(ch[i]);
build();
}
else
init(),find(),dfs(rt);
}
int ans=0;
for(int i=1;i<=poi;i++) ans=max(ans,mn[i]);
printf("%d\n",ans+1);
return 0;
}