bzoj 1396/2865: 识别子串 后缀自动机+线段树
水水的字符串题 ~
#include <map> #include <cstdio> #include <cstring> #include <algorithm> #define M 500003 #define N 1000003 #define lson now<<1 #define rson now<<1|1 #define inf 1000000000 #define setIO(s) freopen(s".in","r",stdin) , freopen(s".out","w",stdout) using namespace std; int last,tot; char str[N]; int rk[N],tax[N],A[N],minn[M<<2],minn2[M<<2]; struct data { int pre,cnt,len,id; map<int,int>ch; }t[N]; void Init() { last=tot=1; } void extend(int c,int pos) { int np=++tot,p=last; t[np].len=t[p].len+1,last=np; for(;p&&!t[p].ch[c];p=t[p].pre) t[p].ch[c]=np; if(!p) t[np].pre=1; else { int q=t[p].ch[c]; if(t[q].len==t[p].len+1) t[np].pre=q; else { int nq=++tot; t[nq].len=t[p].len+1; t[nq].id=t[q].id; t[nq].ch=t[q].ch; t[nq].pre=t[q].pre,t[q].pre=t[np].pre=nq; for(;p&&t[p].ch[c]==q;p=t[p].pre) t[p].ch[c]=nq; } } ++t[np].cnt; t[np].id=pos; } void build(int l,int r,int now) { minn[now]=minn2[now]=inf; if(l==r) return; int mid=(l+r)>>1; if(l<=mid) build(l,mid,lson); if(r>mid) build(mid+1,r,rson); } void update(int l,int r,int now,int L,int R,int v) { if(l>=L&&r<=R) { minn[now]=min(minn[now], v); return; } int mid=(l+r)>>1; if(L<=mid) update(l,mid,lson,L,R,v); if(R>mid) update(mid+1,r,rson,L,R,v); } int query(int l,int r,int now,int p) { if(l==r) return minn[now]; int mid=(l+r)>>1,re=minn[now]; if(p<=mid) re=min(re, query(l,mid,lson,p)); else re=min(re, query(mid+1,r,rson,p)); return re; } void update2(int l,int r,int now,int L,int R,int v) { if(l>=L&&r<=R) { minn2[now]=min(minn2[now], v); return; } int mid=(l+r)>>1; if(L<=mid) update2(l,mid,lson,L,R,v); if(R>mid) update2(mid+1,r,rson,L,R,v); } int query2(int l,int r,int now,int p) { if(l==r) return minn2[now]; int mid=(l+r)>>1, re=minn2[now]; if(p<=mid) re=min(re,query2(l,mid,lson,p)); else re=min(re, query2(mid+1,r,rson,p)); return re; } int main() { // setIO("input"); int n,i,j; Init(); scanf("%s",str+1); n=strlen(str+1); for(i=1;i<=n;++i) extend(str[i]-'a',i); for(i=1;i<=tot;++i) ++tax[t[i].len]; for(i=1;i<=tot;++i) tax[i]+=tax[i-1]; for(i=1;i<=tot;++i) rk[tax[t[i].len]--]=i; build(1,n,1); for(i=tot;i>1;--i) { int u=rk[i]; t[t[u].pre].cnt+=t[u].cnt; t[t[u].pre].id=t[u].id; if(t[u].cnt==1) { update(1,n,1,t[u].id-t[u].len+1,t[u].id-t[t[u].pre].len,t[u].id); update2(1,n,1,t[u].id-t[t[u].pre].len,t[u].id,t[t[u].pre].len+1); } } for(i=1;i<=n;++i) printf("%d\n",min(query(1,n,1,i)-i+1, query2(1,n,1,i))); return 0; }