字尾自動機功能很強大,但碰到多串問題就掛。廣義字尾自動機支援多串操作。思想是在每次插入乙個串後,把las設為1即可,其它操作在parent樹上進行表演。
bzoj 3277
#includeusing namespace std;
typedef long long ll;
const int n=3e5+5;
int n,k,las=1,tot=1,sum[n],num[n],sa[n],vis[n],son[n][26],fa[n],len[n];
string s[n];
ll ans[n],dp[n];
int work(int p,int c)
int ins(int p,int c)
else
return np;}}
void solve()
}for
(int i=1;i<=tot;i++) num[len[i]]++;
for(int i=1;i<=tot;i++) num[i]+=num[i-1];
for(int i=tot;i>=1;i--) sa[num[len[i]]--]=i;
for(int i=2;i<=tot;i++) u=sa[i],dp[u]=dp[fa[u]]+(sum[u]>=k?len[u]-len[fa[u]]:0)
;for
(int i=1;i<=n;i++)
}int main()
solve()
;for
(int i=1;i<=n;i++)
printf
(i==n?"%lld\n"
:"%lld ",ans[i])
;}
bzoj2780
#includeusing namespace std;
const int n=3e5+5;
int n,m,las=1,tot=1,sum[n],sa[n],vis[n],son[n][26],fa[n],len[n];
string s[n];
int work(int p,int c)
int ins(int p,int c)
else
return np;}}
void solve()
}for
(int i=1;i<=m;i++)
}int main()
solve()
;}
bzoj4566
#includeusing namespace std;
typedef long long ll;
const int n=1e6+5;
int n,m,las=1,tot=1,sum[n],num[n],sa[n],f1[n],f2[n],son[n][26],fa[n],len[n];
char s[n],t[n];
bool vis[n],endpos[n][2];
int work(int p,int c)
int ins(int p,int c)
else
return np;}}
int main()
memset
(vis,false,sizeof
(vis));
u=1;
for(int i=1;i<=m;i++)
queueq;
for(int i=2;i<=tot;i++) num[fa[i]]++;
for(int i=1;i<=tot;i++)
if(!num[i]) q.push
(i);
while(!q.empty())
ll ans=0;
for(int i=2;i<=tot;i++)
if(sum[i]==2) ans+=(ll)f1[i]*f2[i]*(len[i]-len[fa[i]])
;printf
("%lld\n",ans)
;}
codeforce 666e
建出廣義字尾自動機,倍增到字串表示的結點,對線段樹進行合併即可,注意在一顆樹上插入的時候為了不影響其它的線段樹,使用copynode把路徑複製,讓線段樹可持久化。
#includeusing namespace std;
const int n=1500000;
int n,m,qq,ans,res,las=1,a[n],rt[n],ls[n*20],rs[n*20],sum[n*20],cnt,num[n],tot=1,son[n][26],fa[n],ff[n][21],len[n];
vectorendpos[n],v;
char s[n],ss[n];
int newnode()
int copynode(int x)
int work(int p,int c)
int ins(int p,int c)
int np=++tot;len[np]=len[p]+1;
while
(p&&!son[p][c]) son[p][c]=np,p=fa[p];
if(!p) fa[np]=1;
else
return np;
}void insert(int l,int r,int x,int &now)
int m=l+r>>1;
if(x<=m)
insert
(l,m,x,ls[now])
; else insert
(m+1,r,x,rs[now])
; sum[now]=max
(sum[ls[now]],sum[rs[now]]);}
int merge(int l,int r,int x,int y)
return now;
}void query(int l,int r,int x,int y,int now)
int m=l+r>>1;
query
(l,m,x,y,ls[now])
;query
(m+1,r,x,y,rs[now]);}
int main()
queueq;
for(int i=2;i<=tot;i++) num[fa[i]]++;
for(int i=1;i<=tot;i++)
if(!num[i]) q.push
(i);
while(!q.empty())
for(int i=v.size
()-1;i>=0;i--)
scanf
("%d",&qq)
; while(qq--)
}
廣義字尾自動機(廣義SAM)
參考部落格 學習筆記 字串 廣義字尾自動機 廣義字尾自動機適用於多串的子串問題。它的dfa可以識別多串中的任意乙個子串。同時也有類似 sam 的一些性質。模板提交處 根據參考部落格所說,有好幾種 假 寫法。比如 每乙個串的開頭設定 lst 為 1 多串拼成乙個大串,中間用 連線 等等 正規寫法 例題...
字尾自動機小結
還沒寫完字尾自動機就來寫小結了 其實是莫比烏斯又推不下去了 其實還是迪哥的hhh 1,有關新建節點的幾種分類討論要記住,大概 yy 板子還是可以用的 2,字首節點指的是當前點所代表的 endpos 集合所對應的串中有乙個原串的字首。具體來說就是新建的 p 節點 3,如果維護樹形結構的話一般是 par...
字尾自動機題目小結
作為乙個傻叉,這兩天才學了sam,做了幾道題。先是模版 字尾自動機 sam suffix automation struct state state root,last state seq maxn 2 int seq cnt state new int len void extend int w ...