廣義字尾自動機小結

2021-09-29 14:48:36 字數 3389 閱讀 5624

字尾自動機功能很強大,但碰到多串問題就掛。廣義字尾自動機支援多串操作。思想是在每次插入乙個串後,把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 ...