青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

AC自動機

Posted on 2011-10-19 19:03 Mato_No1 閱讀(607) 評論(0)  編輯 收藏 引用
AC自動機就是在Trie樹上加入一些失敗指針(fail,類似KMP中的next),使得它在某個結點失配的時候能夠轉移到該結點失敗指針指向的結點繼續匹配,從而實現多串匹配(單主串多子串)。

【1】Trie樹的結構:
首先是結點類型:
struct node {
    
int mul, ch[SZ], fail;
} T[MAXN];
其中SZ是字符集的大小,比如小寫字母集SZ=26,數字集SZ=10等。
另外這個mul表示的是該結點的重復次數(和平衡樹中的比較像),就是這個結點所對應的字符串(從根到該結點路徑上的所有邊上的字符組成的字符串)出現了幾次。
(不過這種表示法MS不是很好……如果有卡空間的,比如結點總數和SZ之積達到了100M以上,而真正的邊又很少的時候……就囧掉了……而如果用指針的話在Linux下面又會CE掉……各位神犇來說一下怎么解決啊囧……)
然后,Trie樹的0號結點(T[0])是空結點(用來代替指針中的NULL),因此真正結點下標從1開始。1號結點(T[1])一般都作為根結點,所以下面直接寫#define root 1。
還有(這句話是除草用的……)Trie樹的字符全部都在邊上而不在點上,因此T[x].ch[c]其實指的是“結點x引出的字符為c的邊所指向的結點”,簡稱結點x的c子結點。

【2】自動機的建立:
首先要建立Trie樹(也就是在空的Trie樹上插入所有要匹配的子串)。這個隨便搞一下就傻掉了,因此直接上代碼:
void ins()
{
    
int len = s0.length(), x = root, c;
    re(i, len) {
        c 
= s0[i] - 97;
        
if (!T[x].ch[c]) {T[x].ch[c] = ++N; T[N].mul = 0; re(j, SZ) T[N].ch[j] = 0;}
        x 
= T[x].ch[c];
    }
    T[x].mul
++;
}
這里string s0是待插入的字符串,定義成全局變量,因為在參數中出現string有可能爆掉。

然后就是建立自動機了。
這一過程其實是用BFS遍歷來實現的。首先,T[root].fail=0(root也是整棵樹中唯一的fail為0的結點)并將root入隊。下面按照BFS的順序依次取出隊所有的點,對于結點i,若它存在k子結點j(也就是j=T[i].ch[k],且j≠0),則結點j入隊,并計算j的失敗指針fail,方法:從T[i].fail(不是i)開始不斷上溯,直到找到一個存在k子結點的結點或者到root都木有找到(結點下標為0,即NULL)。若找到了一個存在k子結點的結點x,則將T[j].fail置為T[x].ch[k],否則(直到root都木有找到),T[j].fail=root。

到這里失敗指針的用處就顯現了:如果匹配到結點x的時候失配(即接下來的一個字符是c而T[x].ch[c]=0),可以立刻轉到T[x].fail進行匹配,因為T[x].fail有以下三個特征:
<1>其深度嚴格小于x的深度;
<2>其代表的字符串一定是x代表的字符串的后綴;
<3>該結點一定是滿足條件<1><2>的所有結點中深度最小的結點;

代碼:
void mkf()
{
    Q[
0= root; T[root].fail = 0;
    
int i, j, x;
    
for (int front=0, rear=0; front<=rear; front++) {
        i 
= Q[front];
        re(k, SZ) 
if (j = T[i].ch[k]) {
            x 
= T[i].fail;
            
while (x && !T[x].ch[k]) x = T[x].fail;
            
if (x) T[j].fail = T[x].ch[k]; else T[j].fail = root;
            Q[
++rear] = j;
        }
    }
}

【3】匹配過程:
在有了失敗指針時,其匹配過程就和KMP差不多了。
設主串為A(代碼中同),依次掃描A[0..A.length()-1]進行匹配。設目前匹配到了第i位,A[i]=c,當前結點為x。匹配過程中將進行以下操作:
<1>成功匹配(T[x]有c子結點),則進入T[x]的c子結點;
<2>失配(T[x]無c子結點),則從T[x].fail開始,沿著失敗指針上溯,直到找到一個有c子結點的結點為止。如果到了root都木有找到這樣的結點,則停止在root處;
<3>設立結點y,從當前的結點x開始不斷上溯到root(注意root也要算,因為子串中可能有空串),將中間所有結點的mul值累加進最終結果(表示這些字符串在主串中出現了,統計次數),如果題目中要求統計不重復的子串個數(如HDU2222),則在累加之后將它們全部置為0,防止下次再次累加。這一步操作實質上就是統計A中所有以A[i]為右端點的子串個數。

這樣,整個過程就傻掉了。

代碼:
void solve()
{
    
int len = A.length(), x = root, y, c; res = 0;
    re(i, len) {
        c 
= A[i] - 97;
        
while (x && !T[x].ch[c]) x = T[x].fail;
        
if (!x) x = root; else x = T[x].ch[c];
        y 
= x;
        
while (y) {res += T[y].mul; T[y].mul = 0; y = T[y].fail;}
    }
}

有關例題:
【1】HDU2222
裸的多串匹配問題,模板題;
有關該題的詳細資料(包括易疵點)見這里
【2】HDU2896
比2222稍難一些,但還是模板題。注意這題的子串木有重復的,因此mul可以設為bool。
【3】HDU3065
統計每個子串出現的次數(可以重復),也是模板題。
以上三題均不卡空間。
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            香港久久久电影| 国产亚洲视频在线观看| 韩国v欧美v日本v亚洲v| aa国产精品| 日韩视频免费观看| 久久亚洲国产成人| 亚洲一区二区三区色| 你懂的一区二区| 日韩视频一区二区三区在线播放免费观看 | 免费一级欧美片在线观看| 蜜臀av性久久久久蜜臀aⅴ四虎| 久久久综合免费视频| 国产精品有限公司| 亚洲一区二区成人在线观看| 亚洲精品美女91| 欧美日本国产在线| 亚洲欧美日韩视频一区| 先锋亚洲精品| 亚洲区在线播放| 亚洲第一久久影院| 欧美激情精品久久久| 欧美成人精品激情在线观看| 正在播放欧美一区| 欧美成人免费播放| 久久精品一本久久99精品| 亚洲精品日韩激情在线电影| 亚洲欧美电影院| 亚洲图片欧美日产| 久久久久久婷| 亚洲人成网在线播放| 亚洲欧美日韩成人| 裸体一区二区| 亚洲专区一二三| 久久精品视频免费| 免费观看在线综合色| 欧美日韩国产一区| 久久久久久成人| 亚洲一区尤物| 久久一区视频| 国产欧美日韩在线播放| 国产美女精品| 一级日韩一区在线观看| 夜夜嗨av一区二区三区免费区| 亚洲在线视频网站| 最新热久久免费视频| 久久久综合网站| 国产精品久久久久一区二区三区| 农夫在线精品视频免费观看| 国产精品视频yy9099| 国产精品成av人在线视午夜片| 美女诱惑一区| 国产亚洲激情视频在线| 亚洲天堂第二页| 亚洲精品孕妇| 欧美日韩播放| 日韩视频在线免费| 国产精品99久久久久久久久久久久| 久久国产福利| 久久久五月天| 午夜精品久久一牛影视| 国产精品国产三级欧美二区| 欧美日韩在线一二三| 欧美性一区二区| 亚洲日本电影在线| 欧美激情黄色片| 99精品欧美一区| 欧美绝品在线观看成人午夜影视| 亚洲国产婷婷| 一区二区日韩精品| 亚洲精品一区二区三区av| 欧美激情在线播放| 国产视频一区在线观看| 激情综合久久| 亚洲精品一区二区三区不| 久久久噜噜噜久久| 久久久久欧美精品| 亚洲黄色av| 亚洲美女精品久久| 欧美性猛交视频| 欧美一区二区三区四区在线观看地址| 久久久久国色av免费看影院 | 男人的天堂亚洲| 亚洲国产日韩欧美在线图片| 亚洲成色999久久网站| 日韩一本二本av| 欧美视频在线观看| 在线观看欧美精品| 午夜在线精品偷拍| 久热国产精品| 国产精品乱人伦中文| 久久久精品久久久久| 免费看黄裸体一级大秀欧美| 一区二区日韩伦理片| 欧美在线观看视频一区二区| 美女被久久久| 亚洲专区一二三| 久久aⅴ国产欧美74aaa| 亚洲国产三级在线| 午夜精品久久久久久久久| 亚洲高清视频一区二区| 亚洲欧美日韩久久精品| 午夜精品久久久99热福利| 亚洲国产成人久久综合一区| 国产精品99久久久久久有的能看| 老司机免费视频一区二区三区| 亚洲日韩视频| 欧美亚洲一区三区| 国产精品午夜视频| 欧美激情一区二区三区蜜桃视频| 欧美三级视频在线播放| 可以看av的网站久久看| 欧美一区二区三区在| 亚洲国产美女久久久久| 亚洲欧美日韩成人| 一区二区三区日韩| 久久久噜噜噜| 午夜精品久久久久久久99樱桃 | 国产精品日韩在线观看| 欧美va天堂va视频va在线| 国产精品久久久久77777| 免费中文字幕日韩欧美| 欧美丝袜一区二区| 欧美承认网站| 久久精品亚洲精品| 一区二区三区四区五区精品| 久久综合色播五月| 欧美在线观看视频在线| 欧美日韩中文在线| 亚洲人永久免费| 亚洲国产成人久久综合一区| 久久精品99国产精品酒店日本| 国产一区二区三区网站| 一区二区欧美视频| 夜夜嗨av一区二区三区| 欧美激情导航| 亚洲国产精品一区二区三区| 欧美色视频在线| 亚洲激情国产精品| 最新国产成人av网站网址麻豆| 亚洲乱码视频| 亚洲人成网站色ww在线| 欧美成人精品影院| 亚洲电影第三页| 亚洲国产精品欧美一二99| 久久手机精品视频| 亚洲二区免费| 一二三区精品| 久久婷婷av| 亚洲黄色一区| 亚洲日本激情| 欧美极品一区| aa级大片欧美三级| 欧美亚洲色图校园春色| 国产一区二区三区最好精华液| 欧美在线免费一级片| 麻豆精品精华液| 亚洲精品乱码久久久久久日本蜜臀 | 欧美国产在线观看| 99国产精品久久久久老师| 亚洲一区在线观看视频| 国产精品一区二区视频 | 亚洲欧美日韩国产精品| 久久色在线观看| 亚洲人在线视频| 欧美日韩国产精品成人| 午夜激情久久久| 欧美激情五月| 亚洲男女毛片无遮挡| 狠狠操狠狠色综合网| 欧美极品一区| 欧美一区二区日韩一区二区| 欧美粗暴jizz性欧美20| 亚洲欧美日韩一区二区三区在线观看 | 久久激情视频久久| 免费不卡亚洲欧美| 在线视频亚洲欧美| 精品电影一区| 国产精品久久久久久久久久直播 | 亚洲欧美激情四射在线日 | 国产日韩精品一区二区三区在线| 欧美在线免费播放| 最新亚洲电影| 久久久久在线观看| 亚洲欧美日韩在线观看a三区 | 男女激情视频一区| 午夜国产精品视频免费体验区| 欧美国产先锋| 久久久久久久波多野高潮日日| 99国产精品国产精品久久| 国产一级久久| 国产精品video| 欧美好吊妞视频| 久久夜色精品国产亚洲aⅴ | 欧美日韩国产在线一区| 久久久久久亚洲精品中文字幕| 一本色道婷婷久久欧美| 欧美福利专区| 六月婷婷久久| 久久久五月天| 亚洲国产精品美女|