【BZOJ1396】识别子串(后缀自动机,线段树)
题意:
一行,一个由小写字母组成的字符串S,长度不超过10^5
思路:论文题
设p为自动机上的合法结点,r为右端点,len=st[fa[p]]]+1
位置[r-st[p]+1,r-len+1]与r-i+1取min,其中i为下标
位置[r-len+1,r]与len取min
建立两棵线段树,分别维护r+1和len
因为只有区间修改和单点查询可以不写lazytag
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 typedef unsigned int uint; 5 typedef unsigned long long ull; 6 typedef pair<int,int> PII; 7 typedef pair<ll,ll> Pll; 8 typedef vector<int> VI; 9 typedef vector<PII> VII; 10 typedef pair<ll,int>P; 11 #define N 100010 12 #define M 210000 13 #define fi first 14 #define se second 15 #define MP make_pair 16 #define pi acos(-1) 17 #define mem(a,b) memset(a,b,sizeof(a)) 18 #define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++) 19 #define per(i,a,b) for(int i=(int)a;i>=(int)b;i--) 20 #define lowbit(x) x&(-x) 21 #define Rand (rand()*(1<<16)+rand()) 22 #define id(x) ((x)<=B?(x):m-n/(x)+1) 23 #define ls p<<1 24 #define rs p<<1|1 25 26 const int MOD=1e9+7,inv2=(MOD+1)/2; 27 double eps=1e-6; 28 int INF=1e9; 29 ll inf=5e13; 30 int dx[4]={-1,1,0,0}; 31 int dy[4]={0,0,-1,1}; 32 33 char s[N]; 34 int p,np,q,nq,k,cas,n; 35 int t[N<<2][2]; 36 37 int read() 38 { 39 int v=0,f=1; 40 char c=getchar(); 41 while(c<48||57<c) {if(c=='-') f=-1; c=getchar();} 42 while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar(); 43 return v*f; 44 } 45 46 void build(int l,int r,int p,int op) 47 { 48 t[p][op]=INF; 49 if(l==r) return; 50 int mid=(l+r)>>1; 51 build(l,mid,ls,op); 52 build(mid+1,r,rs,op); 53 } 54 55 void update(int l,int r,int x,int y,int v,int p,int op) 56 { 57 if(x<=l&&r<=y) 58 { 59 t[p][op]=min(t[p][op],v); 60 return; 61 } 62 int mid=(l+r)>>1; 63 if(x<=mid) update(l,mid,x,y,v,ls,op); 64 if(y>mid) update(mid+1,r,x,y,v,rs,op); 65 } 66 67 int query(int l,int r,int x,int p,int op) 68 { 69 if(l==r) return t[p][op]; 70 int mid=(l+r)>>1; 71 if(x<=mid) return min(t[p][op],query(l,mid,x,ls,op)); 72 else return min(t[p][op],query(mid+1,r,x,rs,op)); 73 } 74 75 struct sam 76 { 77 int cnt; 78 int fa[N<<1],ch[N<<1][26]; 79 int st[N<<1],b[N<<1],bl[N<<1],to[N<<1],size[N<<1]; 80 81 sam() 82 { 83 cnt=np=1; 84 } 85 86 void add(int x,int i) 87 { 88 p=np; st[np=++cnt]=st[p]+1; 89 to[np]=i; 90 while(p&&!ch[p][x]) 91 { 92 ch[p][x]=np; 93 p=fa[p]; 94 } 95 if(!p) fa[np]=1; 96 else if(st[p]+1==st[q=ch[p][x]]) fa[np]=q; 97 else 98 { 99 st[nq=++cnt]=st[p]+1; 100 memcpy(ch[nq],ch[q],sizeof ch[q]); 101 //t[nq]=t[q]; 102 fa[nq]=fa[q]; 103 fa[q]=fa[np]=nq; 104 while(p&&ch[p][x]==q) 105 { 106 ch[p][x]=nq; 107 p=fa[p]; 108 } 109 } 110 } 111 112 void solve() 113 { 114 rep(i,1,cnt) b[st[i]]++; 115 rep(i,1,cnt) b[i]+=b[i-1]; 116 rep(i,1,cnt) bl[b[st[i]]--]=i; 117 int u=1; 118 rep(i,1,n) 119 { 120 u=ch[u][s[i]-'a']; 121 size[u]++; 122 } 123 build(1,n,1,0); 124 build(1,n,1,1); 125 per(i,cnt,1) size[fa[bl[i]]]+=size[bl[i]]; 126 127 rep(i,1,cnt) 128 { 129 int p=bl[i]; 130 if(size[p]>1) continue; 131 int len=st[fa[p]]+1,r=to[p]; 132 update(1,n,r-len+1,r,len,1,0); 133 update(1,n,r-st[p]+1,r-len+1,r+1,1,1); 134 } 135 136 rep(i,1,n) 137 { 138 int t1=query(1,n,i,1,0),t2=-i+query(1,n,i,1,1); 139 printf("%d\n",min(t1,t2)); 140 } 141 142 } 143 }sam; 144 145 146 int main() 147 { 148 scanf("%s",s+1); 149 n=strlen(s+1); 150 rep(i,1,n) sam.add(s[i]-'a',i); 151 sam.solve(); 152 return 0; 153 }
null