1. 程式人生 > >bzoj千題計劃319:bzoj2865: 字串識別(字尾自動機 + 線段樹)

bzoj千題計劃319:bzoj2865: 字串識別(字尾自動機 + 線段樹)

#include<map>
#include<cstdio>
#include<cstring>
#include<algorithm>
 
#define N 500001
 
using namespace std;
 
char s[N];
 
map<int,int>ch[N<<1];
int tot=1;

int fa[N<<1],len[N<<1];
int siz[N<<1]; 
int last=1,p,q,np,nq;
 
int leaf[N];
 
int v[N],sa[N<<1]; struct Segment { int mx[N<<2]; int tag[N<<2]; void down(int k) { mx[k<<1]=min(mx[k<<1],tag[k]); mx[k<<1|1]=min(mx[k<<1|1],tag[k]); tag[k<<1]=min(tag[k<<1],tag[k]); tag[k
<<1|1]=min(tag[k<<1|1],tag[k]); tag[k]=2e9; } void build(int k,int l,int r) { mx[k]=tag[k]=2e9; if(l==r) return; int mid=l+r>>1; build(k<<1,l,mid); build(k<<1|1,mid+1,r); } void change(int
k,int l,int r,int opl,int opr,int w) { if(l>=opl && r<=opr) { mx[k]=min(mx[k],w); tag[k]=min(tag[k],w); return; } int mid=l+r>>1; if(tag[k]!=2e9) down(k); if(opl<=mid) change(k<<1,l,mid,opl,opr,w); if(opr>mid) change(k<<1|1,mid+1,r,opl,opr,w); mx[k]=min(mx[k<<1],mx[k<<1|1]); } int query(int k,int l,int r,int x) { if(l==r) return mx[k]; int mid=l+r>>1; if(tag[k]!=2e9) down(k); if(x<=mid) return query(k<<1,l,mid,x); return query(k<<1|1,mid+1,r,x); } }; Segment tr1,tr2; void extend(int c) { len[np=++tot]=len[last]+1; siz[tot]=1; for(p=last;p && ch[p].find(c)==ch[p].end();p=fa[p]) ch[p][c]=np; if(!p) fa[np]=1; else { q=ch[p][c]; if(len[q]==len[p]+1) fa[np]=q; else { nq=++tot; fa[nq]=fa[q]; ch[nq]=ch[q]; fa[q]=fa[np]=nq; len[nq]=len[p]+1; for(;ch[p][c]==q;p=fa[p]) ch[p][c]=nq; } } last=np; } int main() { scanf("%s",s+1); int n=strlen(s+1); for(int i=1;i<=n;++i) { leaf[i]=tot+1; extend(s[i]-'a'); } for(int i=1;i<=tot;++i) v[len[i]]++; for(int i=1;i<=n;++i) v[i]+=v[i-1]; for(int i=1;i<=tot;++i) sa[v[len[i]]--]=i; int x; for(int i=tot;i;--i) { x=sa[i]; siz[fa[x]]+=siz[x]; } tr1.build(1,1,n); tr2.build(1,1,n); int l,r,end; for(int x=2;x<=tot;++x) if(siz[x]==1) { l=len[fa[x]]; r=len[x]; end=len[x]; tr1.change(1,1,n,end-l,end,l+1); tr2.change(1,1,n,end-r+1,end-l,end+1); } int a,b; for(int i=1;i<=n;++i) { a=tr1.query(1,1,n,i); b=tr2.query(1,1,n,i)-i; printf("%d\n",min(a,b)); } return 0; }

相關推薦

bzoj計劃319bzoj2865: 字串識別字尾自動機 + 線段

#include<map> #include<cstdio> #include<cstring> #include<algorithm> #define N 500001 using namespace std; char s[

bzoj計劃314bzoj3238: [Ahoi2013]差異字尾陣列+st表+單調棧

#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define N 500001 int n

bzoj計劃308bzoj4589: Hard Nim倍增FWT+生成函式

#include<cstdio> #include<cstring> using namespace std; #define N 50001 const int mod=1e9+7; const int M=1<<16; int inv

bzoj計劃315bzoj3172: [Tjoi2013]單詞AC自動機

#include<queue> #include<cstdio> #include<cstring> using namespace std; #define N 2000001 using namespace std; int pos[20

bzoj計劃311bzoj5017: [Snoi2017]炸彈線段優化tarjan構圖

#include<cstdio> #include<vector> #include<iostream> #include<algorithm> using namespace std; const int mod=1e9+7;

bzoj計劃318bzoj1396: 識別子串字尾自動機 + 線段

#include<cstdio> #include<cstring> #include<algorithm> #define N 100001 using namespace std; char s[N]; int ch[N<&

bzoj 1396: 識別子串 字尾自動機+線段

1396: 識別子串 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 308  Solved: 190 [Submit][Status][Discuss] Description Input 一行,一個由小寫字母組成

bzoj計劃310bzoj5285: [Hnoi2018]尋寶遊戲(思維+雜湊)

#include<cstdio> #include<algorithm> #define N 5001 using namespace std; const int mod=1e9+7; int bit[N]; char s[N]; int has

bzoj計劃316bzoj3173: [Tjoi2013]最長上升子序列二分+狀陣列

#include<cstdio> #include<iostream> #include<algorithm> using namespace std; #define N 100001 #define lowbit(x) x&-x

bzoj計劃309bzoj4332: JSOI2012 分零食分治+FFT

#include<cmath> #include<cstdio> #include<algorithm> using namespace std; const int M=1<<17; #define N 10001 int m,

bzoj計劃321bzoj5251: [2018多省省隊聯測]劈配網路流 + 二分

#include<queue> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #d

bzoj計劃312bzoj2119: 股市的預測字尾陣列+st表

#include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #d

bzoj計劃317bzoj4650: [Noi2016]優秀的拆分字尾陣列+差分

#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define N 30002 using namespace std; int n;

bzoj計劃323bzoj1951: [Sdoi2010]古代豬文Lucas+CRT+尤拉定理

#include<cmath> #include<cstdio> #include<iostream> using namespace std; const int mod=999911659; const int phi=mod-1; typ

bzoj計劃322bzoj2561: 最小生成樹最小割

#include<cstdio> #include<queue> #include<cstring> #include<iostream> #include<algorithm> using namespace std;

bzoj計劃324bzoj5249: [2018多省省隊聯測]IIIDX線段

#include<cmath> #include<cstdio> #include<iostream> #include<algorithm> using namespace std; #define N 500001 int d[N

bzoj計劃313bzoj3879: SvT字尾陣列+st表+單調棧

#include<cstdio> #include<iostream> #include<algorithm> using namespace std; #define N 500001 #define M 3000001 int n,m,mm;

bzoj計劃320bzoj4939: [Ynoi2016]掉進兔子洞莫隊 + bitset

#include<cmath> #include<cstdio> #include<bitset> #include<cstring> #include<iostream> #include<algorithm> us

bzoj 2588 Spoj 10628. Count on a tree 可持久化線段

change lca 權值線段樹 mat sin urn problem sample des Spoj 10628. Count on a tree Time Limit: 12 Sec Memory Limit: 128 MBSubmit: 7669 Solv

BZOJ.5417.[NOI2018]你的名字(字尾自動機 線段合併)

LOJ 洛谷 BZOJ 考慮\(l=1,r=|S|\)的情況: 對\(S\)串建SAM,\(T\)在上面匹配,可以得到每個位置\(i\)的字尾的最長匹配長度\(mx[i]\)。 因為要去重,對\(T\)也建SAM,計算上面所有節點的答案。記\(pos[i]\)表示\(i\)節點第一次出現的下標(同一節點代表