【BZOJ】3145: [Feyat cup 1.5]Str-set&SA
阿新 • • 發佈:2019-01-03
傳送門:bzoj3145
題解
完全是膜著Claris的code寫的,程式碼就不用看了。。。
不考慮複雜度我們可以列舉
分別表示串
中那個不同的位置。
則
可以在 末尾加一個字符集外的字元後再連上 。正著求出 翻轉後求出 。
可以通過固定一維列舉另一維 的複雜度降到 :從大到小列舉 的值,即按 排序,並查集維護 的連續區間啟發式合併 所在的區間,逐個插入更新答案。
每段連續區間中 維護這些串對應的在 中的 的 ,對於插入的串找到集合中最接近它對應的字首 求個 即可。
注意以上都是強制 均 的情況,還有可能只有 ,需要最後特殊列舉判斷一下。
程式碼
#include<bits/stdc++.h>
#define mem(f) memset(f,0,sizeof(f))
using namespace std;
const int N=4e5+100;
int n,la,lb,d[18][N],bin[30],lg[N],id[N],sz[N];
int c[N],t1[N],t2[N],f[N],ans,lcp;
int head[N],nxt[N<<1],to[N<<1],tot;
char s[N],t[N];bool ca[N],cb[N];
set<int>sa[N],sb[N];
set<int>::iterator it;
inline void lk(int u,int v)
{to[++tot]=v;nxt[tot]=head[u];head[u]=tot;}
struct SA{
int sa[N],rk[N],ht[N];char s[N];
inline void build()
{
int i,j,k,p,m=128,*x=t1,*y=t2;
for(i=1;i<=n;++i) c[(x[i]=(int)s[i])]++;
for(i=1;i<=m;++i) c[i]+=c[i-1];
for(i=n;i;--i) sa[c[x[i]]--]=i;
for(k=1;k<=n;k<<=1){
for(p=0,i=n-k+1;i<=n;++i) y[++p]=i;
for(i=1;i<=n;++i) if(sa[i]>k) y[++p]=sa[i]-k;
for(i=1;i<=m;++i) c[i]=0;
for(i=1;i<=n;++i) c[x[y[i]]]++;
for(i=1;i<=m;++i) c[i]+=c[i-1];
for(i=n;i;--i) sa[c[x[y[i]]]--]=y[i];
p=1;swap(x,y);x[sa[1]]=1;
for(i=2;i<=n;++i){
p+=((y[sa[i]]!=y[sa[i-1]])||(y[sa[i]+k]!=y[sa[i-1]+k]));
x[sa[i]]=p;
}
if(p>=n) break;
m=p;
}
for(i=1;i<=n;++i) rk[sa[i]]=i;
for(p=0,i=1;i<=n;++i){
if(rk[i]==1) {p=0;continue;}
for(p=max(0,p-1),j=sa[rk[i]-1];i+p<=n && j+p<=n && s[i+p]==s[j+p];++p);
ht[rk[i]]=p;
}
}
inline void mk()
{
int i,j;bin[0]=1;
for(i=1;i<30;++i) bin[i]=bin[i-1]<<1;
for(i=2;i<N;++i) lg[i]=lg[i>>1]+1;
for(i=1;i<=n;++i) d[0][i]=ht[i];
for(i=1;bin[i]<=n;++i)
for(j=1;j+bin[i]-1<=n;++j)
d[i][j]=min(d[i-1][j],d[i-1][j+bin[i-1]]);
}
}A,B;
inline int cal(int x,int y)
{
if(x>y) swap(x,y);int bs=lg[y-x];
return min(d[bs][x+1],d[bs][y-bin[bs]+1]);
}
void dfs(int x,int fr,int bl)
{
int i,j;f[x]=bl;
if(A.sa[x]<=la){
i=A.sa[x]-2;if(i>0){
i=B.rk[n-i+1];sa[bl].insert(i);
it=sb[bl].lower_bound(i);
if(it!=sb[bl].end()) ans=max(ans,lcp+cal(i,*it));
if(it!=sb[bl].begin()) it--,ans=max(ans,lcp+cal(i,*it));
}
}else if(A.sa[x]>la+1){
i=A.sa[x]-2;if(i>la+1){
i=B.rk[n-i+1];sb[bl].insert(i);
it=sa[bl].lower_bound(i);
if(it!=sa[bl].end()) ans=max(ans,lcp+cal(i,*it));
if(it!=sa[bl].begin()) it--,ans=max(ans,lcp+cal(i,*it));
}
}
for(i=head[x];i;i=nxt[i]) if(to[i]!=fr) dfs(to[i],x,bl);
}
inline void ext(int x,int y)
{
x=f[x];y=f[y];
if(sz[x]>sz[y]) swap(x,y);
if((ca[x]&&cb[y])||(cb[x]&&ca[y])) ans=max(ans,lcp-1);
ca[y]|=ca[x];cb[y]|=cb[x];sz[y]+=sz[x];
sa[x].clear();sb[x].clear();
lk(x,y);lk(y,x);dfs(x,y,y);
}
inline bool cmp(const int&x,const int&y){return A.ht[x]>A.ht[y];}
int