日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

BZOJ.3277.串(广义后缀自动机)

發(fā)布時(shí)間:2025/4/16 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 BZOJ.3277.串(广义后缀自动机) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

題目鏈接

\(Description\)

給定n個(gè)串和K,求每個(gè)串中有多少個(gè)子串是這n個(gè)串中至少K個(gè)串的子串。

\(Solution\)

同上題,我們可以算出每個(gè)節(jié)點(diǎn)所代表的串出現(xiàn)在了幾個(gè)串中;而且我們知道,對(duì)于每個(gè)節(jié)點(diǎn)i,它代表的串的數(shù)量為len[i]-len[fa[i]]。
建立廣義后綴自動(dòng)機(jī),預(yù)處理每個(gè)節(jié)點(diǎn)的cnt。每個(gè)節(jié)點(diǎn)的val可以根據(jù)cnt是否>=K設(shè)為len[i]-len[fa[i]]或0。
我們要求的是所有子串,所以如果統(tǒng)計(jì)val[i],也要算上val[fa[i]],val[fa[fa[i]]]...直接建出parent樹(shù)從上到下DFS更新每個(gè)點(diǎn)。
對(duì)于每個(gè)要求答案的串,在SAM上走一遍并累加所有經(jīng)過(guò)節(jié)點(diǎn)的更新后的val即可。
求答案的時(shí)候因?yàn)椴环奖愦嫠性?#xff0c;so用個(gè)鏈表/vector存下所有經(jīng)過(guò)點(diǎn)來(lái)。

如果有拓?fù)湫虻脑捯膊恍枰╬arent樹(shù)DFS。

我并不想看100+行的SA+二分。。

跑得略慢啊

//30740kb 612ms #include <cstdio> #include <vector> #include <cstring> #include <algorithm> #define gc() getchar() typedef long long LL; const int N=2e5+5;//∑len <= 1e5 ?struct Suffix_Automaton {int n,K,las,tot,fa[N],son[N][26],len[N],cnt[N],bef[N],Enum,H[N],nxt[N],to[N];//parent樹(shù)空間是2n啊 LL val[N];char s[N>>1];std::vector<int> v[N>>1];void Init(int nn){n=nn, scanf("%d",&K), las=tot=1;}inline void AddEdge(int u,int v){to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum;}void Insert(int now,int c){int p=las,np=++tot; len[las=np]=len[p]+1;for(; p&&!son[p][c]; p=fa[p]) son[p][c]=np;if(!p) fa[np]=1;else{int q=son[p][c];if(len[q]==len[p]+1) fa[np]=q;else{int nq=++tot;len[nq]=len[p]+1, bef[nq]=bef[q], cnt[nq]=cnt[q];memcpy(son[nq],son[q],sizeof son[q]);fa[nq]=fa[q], fa[q]=fa[np]=nq;for(; son[p][c]==q; p=fa[p]) son[p][c]=nq;}}v[now].push_back(np);for(; bef[np]!=now&&np; np=fa[np])++cnt[np], bef[np]=now;}void Build(int now){scanf("%s",s), las=1;//las=1! for(int i=0,l=strlen(s); i<l; ++i)Insert(now,s[i]-'a');}void DFS(int x){val[x]+=val[fa[x]];for(int i=H[x]; i; i=nxt[i]) DFS(to[i]);}void Solve(){for(int i=2; i<=tot; ++i){AddEdge(fa[i],i);if(cnt[i]<K) val[i]=0;else val[i]=len[i]-len[fa[i]];}DFS(1);for(int i=1; i<=n; ++i){LL res=0;for(int j=0,l=v[i].size(); j<l; ++j)res+=val[v[i][j]];printf("%lld ",res);}} }sam;int main() {int n; scanf("%d",&n), sam.Init(n);for(int i=1; i<=n; ++i) sam.Build(i);sam.Solve();return 0; }

轉(zhuǎn)載于:https://www.cnblogs.com/SovietPower/p/9241115.html

總結(jié)

以上是生活随笔為你收集整理的BZOJ.3277.串(广义后缀自动机)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。