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

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

生活随笔

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

编程问答

AC自动机-洛谷3121 [USACO15FEB]审查(黄金)Censoring (Gold)

發(fā)布時(shí)間:2025/3/21 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 AC自动机-洛谷3121 [USACO15FEB]审查(黄金)Censoring (Gold) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

https://www.luogu.org/problem/show?pid=3121#sub
首先題目看清楚

FJ注意到列表中的單詞不會(huì)出現(xiàn)一個(gè)單詞是另一個(gè)單詞子串的情況,這意味著每個(gè)列表中的單詞在S中出現(xiàn)的開(kāi)始位置是互不相同的

這意味著你在找答案時(shí),當(dāng)一個(gè)節(jié)點(diǎn)正常訪(fǎng)問(wèn)的時(shí)候,你不用去尋找fail;
你只要在匹配失敗的時(shí)候取fail就好了;
關(guān)于fail的意義,可以看我AC自動(dòng)機(jī)的博客;
然后我們?cè)谠靦rie時(shí),順便把一個(gè)字符串的長(zhǎng)度記錄下來(lái);
end=一個(gè)字符串的長(zhǎng)度;
然后我們開(kāi)2個(gè)棧;
a[]記錄當(dāng)前搜到那個(gè)點(diǎn);
b[]記錄當(dāng)前搜那個(gè)char;
然后如果發(fā)現(xiàn)當(dāng)前節(jié)點(diǎn)是end;
直接彈出棧頂end個(gè)元素;
更新now指針,繼續(xù)搜;
好了;
有個(gè)事情要注意;
我原始的AC自動(dòng)機(jī);

void makezyy(){for(int i=0;i<26;i++)if(T[0].nxt[i])q[++r]=T[0].nxt[i];while(r>l){int x=q[++l];for(int i=0;i<26;i++)if(T[x].nxt[i]){q[++r]=T[x].nxt[i];int y=T[x].fail;while(y&&!T[y].nxt[i])y=T[y].fail;T[q[r]].fail=T[y].nxt[i];}} } void find(int m){int o=0;for(int i=0;i<m;i++){int x=s[i]-'a';int y=o;while(y&&!T[y].nxt[x])y=T[y].fail;o=T[y].nxt[x];a[++tot]=o;b[tot]=i;if(T[o].E){tot-=T[o].E;o=a[tot];} } }

大家看,這個(gè)好理解,但是用了while循環(huán),會(huì)被卡一個(gè)點(diǎn);
那我們看看更優(yōu)的寫(xiě)法;

void makezyy(){for(int i=0;i<26;i++)if(T[0].nxt[i])q[++r]=T[0].nxt[i];while(r>l){int x=q[++l];for(int i=0;i<26;i++)if(!T[x].nxt[i])T[x].nxt[i]=T[T[x].fail].nxt[i];else{q[++r]=T[x].nxt[i];T[T[x].nxt[i]].fail=T[T[x].fail].nxt[i];}} } void find(int m){int o=0;for(int i=0;i<m;i++){o=T[o].nxt[s[i]-'a'];a[++tot]=o;b[tot]=i;if(T[o].E){tot-=T[o].E;o=a[tot];} } }

種方法巧妙地運(yùn)用地推;
兩種方法求出的fail值是相同的;
但是這種方法會(huì)無(wú)法辨別出某個(gè)節(jié)點(diǎn)在一開(kāi)始有沒(méi)有某個(gè)兒子;
因?yàn)閙akezyy之后空的兒子自動(dòng)變成了fail;
好像還可以?xún)?yōu)化的吧;

#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> using namespace std; struct trie{int nxt[26],fail,E; }T[100005]; int q[100005],l,r,a[100005],b[100005],tot; int n,m,ll; char s[100005],c[100005]; void init(int m){int o=0;for(int i=0;i<m;i++){int x=c[i]-'a';if(!T[o].nxt[x])T[o].nxt[x]=++ll;o=T[o].nxt[x];}T[o].E=m; } void makezyy(){for(int i=0;i<26;i++)if(T[0].nxt[i])q[++r]=T[0].nxt[i];while(r>l){int x=q[++l];for(int i=0;i<26;i++)if(!T[x].nxt[i])T[x].nxt[i]=T[T[x].fail].nxt[i];else{q[++r]=T[x].nxt[i];T[T[x].nxt[i]].fail=T[T[x].fail].nxt[i];}} } void find(int m){int o=0;for(int i=0;i<m;i++){o=T[o].nxt[s[i]-'a'];a[++tot]=o;b[tot]=i;if(T[o].E){tot-=T[o].E;o=a[tot];} } } int main() {scanf("%s",s);scanf("%d",&n);while(n--)scanf("%s",c),init(strlen(c));makezyy();find(strlen(s));for(int i=1;i<=tot;i++)cout<<s[b[i]]; }

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

總結(jié)

以上是生活随笔為你收集整理的AC自动机-洛谷3121 [USACO15FEB]审查(黄金)Censoring (Gold)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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