bzoj1396 识别子串
题解:
首先我们知道对于size==1的点是只出现一次的
存疑:为什么新增点不会size==1
那么问题就变成区间取等差数列,区间取最小值
分别线段树维护就可以了
代码:
#include <bits/stdc++.h> #define IL inline #define ll long long #define rint register int #define rep(i,h,t) for (rint i=h;i<=t;i++) #define dep(i,t,h) for (rint i=t;i>=h;i--) using namespace std; const int INF=1e9; const int N=3e5; char s[N]; int size[N],len[N],ch[N][26]; int lst=1,node=1,t[N],a[N],fa[N],pos[N],pl; void extend(int c) { int f=lst; if (ch[f][c]&&len[ch[f][c]]==len[f]+1) { lst=ch[f][c]; return; } int p=++node; lst=p; len[p]=len[f]+1; //size[p][pl]=1; while (f&&!ch[f][c]) ch[f][c]=p,f=fa[f]; if (!f) { fa[p]=1; return;}; int x=ch[f][c],y=++node; if (len[f]+1==len[x]) {fa[p]=x; node--;return;}; len[y]=len[f]+1; fa[y]=fa[x]; fa[x]=fa[p]=y; memcpy(ch[y],ch[x],sizeof(ch[x])); while (f&&ch[f][c]==x) ch[f][c]=y,f=fa[f]; } IL int min(int x,int y) { if (x>y) return(y); else return(x); } IL int max(int x,int y) { if (x<y) return(y); else return(x); } IL void minn(int &x,int y) { if (x>y) x=y; } IL void maxn(int &x,int y) { if (x<y) x=y; } const int N1=N*4; struct sgt{ int lazy1[N1],lazy2[N1]; sgt() { rep(i,0,N1-1) lazy1[i]=lazy2[i]=INF; } #define mid ((h+t)/2) IL void down(int x,int h,int t) { minn(lazy1[x*2],lazy1[x]); minn(lazy1[x*2+1],lazy1[x]-(mid-h+1)); minn(lazy2[x*2],lazy2[x]); minn(lazy2[x*2+1],lazy2[x]); } void change1(int x,int h,int t,int h1,int t1,int k) { if (h1<=h&&t<=t1) { minn(lazy1[x],k); return; } down(x,h,t); if (h1<=mid) change1(x*2,h,mid,h1,t1,k); if (mid<t1) change1(x*2+1,mid+1,t,h1,t1,k-(mid-h+1)); } void change2(int x,int h,int t,int h1,int t1,int k) { if (h1<=h&&t<=t1) { minn(lazy2[x],k); return; } down(x,h,t); if (h1<=mid) change2(x*2,h,mid,h1,t1,k); if (mid<t1) change2(x*2+1,mid+1,t,h1,t1,k); } int query(int x,int h,int t,int pos) { if (h==t) { return(min(lazy1[x],lazy2[x])); } down(x,h,t); if (pos<=mid) return(query(x*2,h,mid,pos)); else return(query(x*2+1,mid+1,t,pos)); } }S; int main() { freopen("1.in","r",stdin); freopen("1.out","w",stdout); ios::sync_with_stdio(false); cin>>s; int l=strlen(s); int n=l; rep(i,1,l) extend(s[i-1]-'a'),size[lst]++,pos[lst]=i; rep(i,1,node) t[len[i]]++; rep(i,1,node) t[i]+=t[i-1]; rep(i,1,node) a[t[len[i]]--]=i; dep(i,node,1) { int x=a[i]; size[fa[x]]+=size[x]; } rep(i,1,node) if (size[i]==1) { S.change1(1,1,n,pos[i]-len[i]+1,pos[i]-len[fa[i]],len[i]); if (fa[i]) S.change2(1,1,n,pos[i]-len[fa[i]]+1,pos[i],1+len[fa[i]]); } rep(i,1,n) cout<<S.query(1,1,n,i)<<endl; return 0; }