4698: Sdoi2008 Sandy的卡片
阿新 • • 發佈:2018-12-20
前言
總之這個東西說起來很麻煩就是了,
思路
差分合並+字尾陣列+二分(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<<"\n"; return 0; }