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

icecream

我的代碼備份!

AC 自動機算法詳解(轉)

首先簡要介紹一下AC自動機:Aho-Corasick automation,該算法在1975年產生于貝爾實驗室,是著名的多模匹配算法之一。一個常見的例子就是給出n個單詞,再給出一段包含m個字符的文章,讓你找出有多少個單詞在文章里出現過。要搞懂AC自動機,先得有模式樹(字典樹)Trie和KMP模式匹配算法的基礎知識。AC自動機算法分為3步:構造一棵Trie樹,構造失敗指針和模式匹配過程。
     如果你對KMP算法和了解的話,應該知道KMP算法中的next函數(shift函數或者fail函數)是干什么用的。KMP中我們用兩個指針i和j分別表示,A[i-j+ 1..i]與B[1..j]完全相等。也就是說,i是不斷增加的,隨著i的增加j相應地變化,且j滿足以A[i]結尾的長度為j的字符串正好匹配B串的前 j個字符,當A[i+1]≠B[j+1],KMP的策略是調整j的位置(減小j值)使得A[i-j+1..i]與B[1..j]保持匹配且新的B[j+1]恰好與A[i+1]匹配,而next函數恰恰記錄了這個j應該調整到的位置。同樣AC自動機的失敗指針具有同樣的功能,也就是說當我們的模式串在Tire上進行匹配時,如果與當前節點的關鍵字不能繼續匹配的時候,就應該去當前節點的失敗指針所指向的節點繼續進行匹配。
      看下面這個例子:給定5個單詞:say she shr he her,然后給定一個字符串yasherhs。問一共有多少單詞在這個字符串中出現過。我們先規定一下AC自動機所需要的一些數據結構,方便接下去的編程。
1 const int kind = 26;
2 struct node{  
3      node *fail;       //失敗指針
4      node *next[kind]; //Tire每個節點的個子節點(最多個字母)
5     int count;        //是否為該單詞的最后一個節點
6      node(){           //構造函數初始化
7          fail=NULL;
8          count=0;
9          memset(next,NULL,sizeof(next));
10      }
11 }*q[500001];          //隊列,方便用于bfs構造失敗指針
12 char keyword[51];     //輸入的單詞
13 char str[1000001];    //模式串
14 int head,tail;        //隊列的頭尾指針

有了這些數據結構之后,就可以開始編程了:
    首先,將這5個單詞構造成一棵Tire,如圖-1所示。

 

1 void insert(char *str,node *root){
2      node *p=root;
3     int i=0,index;  
4     while(str[i]){
5          index=str[i]-'a';
6         if(p->next[index]==NULL) p->next[index]=new node();  
7          p=p->next[index];
8          i++;
9      }
10      p->count++;     //在單詞的最后一個節點count+1,代表一個單詞
11 }

在構造完這棵Tire之后,接下去的工作就是構造下失敗指針。構造失敗指針的過程概括起來就一句話:設這個節點上的字母為C,沿著他父親的失敗指針走,直到走到一個節點,他的兒子中也有字母為C的節點。然后把當前節點的失敗指針指向那個字母也為C的兒子。如果一直走到了root都沒找到,那就把失敗指針指向root。具體操作起來只需要:先把root加入隊列(root的失敗指針指向自己或者NULL),這以后我們每處理一個點,就把它的所有兒子加入隊列,隊列為空。

1 void build_ac_automation(node *root){
2     int i;
3      root->fail=NULL;
4      q[head++]=root;
5     while(head!=tail){
6          node *temp=q[tail++];
7          node *p=NULL;
8         for(i=0;i<26;i++){
9             if(temp->next[i]!=NULL){
10                 if(temp==root) temp->next[i]->fail=root;                 
11                 else{
12                      p=temp->fail;
13                     while(p!=NULL){  
14                         if(p->next[i]!=NULL){
15                              temp->next[i]->fail=p->next[i];
16                             break;
17                          }
18                          p=p->fail;
19                      }
20                     if(p==NULL) temp->next[i]->fail=root;
21                  }
22                  q[head++]=temp->next[i];  
23              }
24          }   
25      }
26 }

    從代碼觀察下構造失敗指針的流程:對照圖-2來看,首先root的fail指針指向NULL,然后root入隊,進入循環。第1次循環的時候,我們需要處理2個節點:root->next[‘h’-‘a’](節點h) 和 root->next[‘s’-‘a’](節點s)。把這2個節點的失敗指針指向root,并且先后進入隊列,失敗指針的指向對應圖-2中的(1),(2)兩條虛線;第2次進入循環后,從隊列中先彈出h,接下來p指向h節點的fail指針指向的節點,也就是root;進入第13行的循環后,p=p->fail也就是p=NULL,這時退出循環,并把節點e的fail指針指向root,對應圖-2中的(3),然后節點e進入隊列;第3次循環時,彈出的第一個節點a的操作與上一步操作的節點e相同,把a的fail指針指向root,對應圖-2中的(4),并入隊;第4次進入循環時,彈出節點h(圖中左邊那個),這時操作略有不同。在程序運行到14行時,由于p->next[i]!=NULL(root有h這個兒子節點,圖中右邊那個),這樣便把左邊那個h節點的失敗指針指向右邊那個root的兒子節點h,對應圖-2中的(5),然后h入隊。以此類推:在循環結束后,所有的失敗指針就是圖-2中的這種形式。

   最后,我們便可以在AC自動機上查找模式串中出現過哪些單詞了。匹配過程分兩種情況:(1)當前字符匹配, 表示從當前節點沿著樹邊有一條路徑可以到達目標字符,此時只需沿該路徑走向下一個節點繼續匹配即可,目標字符串指針移向下個字符繼續匹配;(2)當前字符 不匹配,則去當前節點失敗指針所指向的字符繼續匹配,匹配過程隨著指針指向root結束。重復這2個過程中的任意一個,直到模式串走到結尾為止。
1 int query(node *root){
2     int i=0,cnt=0,index,len=strlen(str);
3      node *p=root;  
4     while(str[i]){  
5          index=str[i]-'a';  
6         while(p->next[index]==NULL && p!=root) p=p->fail;
7          p=p->next[index];
8          p=(p==NULL)?root:p;
9          node *temp=p;
10         while(temp!=root && temp->count!=-1){
11              cnt+=temp->count;
12              temp->count=-1;
13              temp=temp->fail;
14          }
15          i++;                 
16      }    
17     return cnt;
18 }
    對照圖-2,看一下模式匹配這個詳細的流程,其中模式串為yasherhs。對于i=0,1。Trie中沒有對應的路徑,故不做任何操作;i=2,3,4 時,指針p走到左下節點e。因為節點e的count信息為1,所以cnt+1,并且講節點e的count值設置為-1,表示改單詞已經出現過了,防止重復 計數,最后temp指向e節點的失敗指針所指向的節點繼續查找,以此類推,最后temp指向root,退出while循環,這個過程中count增加了 2。表示找到了2個單詞she和he。當i=5時,程序進入第5行,p指向其失敗指針的節點,也就是右邊那個e節點,隨后在第6行指向r節點,r節點的 count值為1,從而count+1,循環直到temp指向root為止。最后i=6,7時,找不到任何匹配,匹配過程結束。

posted on 2009-04-28 19:31 icecream 閱讀(449) 評論(0)  編輯 收藏 引用 所屬分類: String


只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


My Links

Blog Stats

常用鏈接

留言簿

隨筆分類

隨筆檔案

文章分類

ACMER

搜索

最新評論

閱讀排行榜

評論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            国产资源精品在线观看| 激情欧美亚洲| 亚洲视频在线观看一区| 日韩视频不卡中文| 欧美亚洲第一页| 午夜一区不卡| 性欧美大战久久久久久久免费观看 | 99精品欧美一区二区三区综合在线 | 国产一区二区按摩在线观看| 久久久久国产精品麻豆ai换脸| 久久成人18免费网站| 农夫在线精品视频免费观看| 久久久久9999亚洲精品| 亚洲人成人一区二区在线观看| 亚洲区欧美区| 欧美日韩视频在线一区二区观看视频| 国产精品99久久久久久白浆小说| 亚洲私人黄色宅男| 国产视频亚洲精品| 你懂的一区二区| 国产精品porn| 久久精品最新地址| 欧美国产日本韩| 午夜精品久久久久久久99樱桃| 欧美在线短视频| 亚洲美女91| 亚洲一区三区电影在线观看| 在线播放一区| 亚洲视频在线观看网站| 亚洲电影一级黄| 亚洲天堂av在线免费观看| 黄色亚洲免费| 一区二区三区精品| 在线播放不卡| 亚洲自拍偷拍视频| 日韩视频不卡中文| 久久精品三级| 午夜伦理片一区| 欧美激情四色 | 亚洲一区二区在线播放| 久久午夜激情| 在线精品福利| 亚洲综合视频1区| 日韩午夜精品视频| 久久亚洲综合色一区二区三区| 亚洲无人区一区| 久热精品在线视频| 久久五月婷婷丁香社区| 国产精品久久久久久久浪潮网站| 亚洲国产精品久久| 亚洲国产精品热久久| 香蕉尹人综合在线观看| 在线综合亚洲| 欧美国产精品专区| 欧美成人午夜影院| 一区视频在线播放| 欧美中文字幕第一页| 午夜天堂精品久久久久| 国产精品vvv| 亚洲美女区一区| 国产精品99久久久久久www| 欧美国产日韩视频| 91久久综合亚洲鲁鲁五月天| 亚洲欧洲精品成人久久奇米网| 久久aⅴ国产紧身牛仔裤| 欧美一区二区三区久久精品茉莉花| 欧美日韩国产免费观看| 亚洲免费观看高清完整版在线观看熊| 亚洲区国产区| 欧美久久视频| 99国产精品国产精品毛片| 99精品国产在热久久| 欧美精品三级在线观看| 亚洲精品久久视频| 亚洲一区3d动漫同人无遮挡| 欧美日韩视频在线一区二区| 99re6热只有精品免费观看| 99人久久精品视频最新地址| 欧美精品日韩综合在线| 亚洲精品影院在线观看| 亚洲一区www| 国产欧美一区二区三区在线看蜜臀 | 欧美大片va欧美在线播放| 亚洲高清一区二区三区| 欧美国产亚洲精品久久久8v| 99av国产精品欲麻豆| 亚洲一区日韩| 国产一区二区三区奇米久涩 | 中文高清一区| 国内伊人久久久久久网站视频 | 亚洲国产成人午夜在线一区| 亚洲黄网站黄| 欧美日韩一区三区四区| 亚洲欧美美女| 老司机一区二区| 亚洲日本中文字幕区| 国产精品v欧美精品∨日韩| 亚洲欧美日韩天堂一区二区| 久久综合激情| 一区二区三区高清| 国产亚洲综合在线| 欧美成人综合| 午夜精品久久久久久99热| 欧美成人精品在线| 亚洲免费一在线| 黄色欧美成人| 国产精品少妇自拍| 免费永久网站黄欧美| 亚洲欧美激情一区二区| 亚洲成人在线视频播放| 国产伦精品一区二区三区视频孕妇 | 亚洲无吗在线| 欧美福利视频一区| 欧美亚洲午夜视频在线观看| 亚洲精品在线一区二区| 国产日韩一区| 欧美日韩情趣电影| 久久噜噜亚洲综合| 亚洲主播在线播放| 亚洲精品在线一区二区| 女同一区二区| 久久精品国产91精品亚洲| 一级日韩一区在线观看| 伊人成年综合电影网| 国产精品你懂的在线| 欧美精品久久久久a| 久久尤物视频| 久久精品国产久精国产一老狼| 在线中文字幕日韩| 亚洲国产日韩一区| 免费在线日韩av| 久久人人爽人人爽| 欧美一区二区在线视频| 亚洲一区二区伦理| 中日韩在线视频| 亚洲精品国产精品乱码不99按摩| 极品尤物久久久av免费看| 国产欧美精品在线| 国产精品啊啊啊| 欧美日韩久久精品| 欧美特黄一区| 欧美午夜不卡影院在线观看完整版免费| 欧美大片va欧美在线播放| 久久久久久精| 久久久精品性| 久久亚洲不卡| 麻豆精品一区二区综合av| 久久久亚洲国产美女国产盗摄| 欧美中文在线观看| 久久一日本道色综合久久| 久久久久成人网| 久久综合给合| 欧美成人在线免费观看| 欧美久久九九| 国产精品久久97| 国产日韩欧美视频| 一区二区三区在线免费观看| 精品福利免费观看| 亚洲黄色尤物视频| 一区二区三区四区精品| 亚洲砖区区免费| 欧美一级午夜免费电影| 久久精品一区二区三区中文字幕| 久久男人av资源网站| 女人色偷偷aa久久天堂| 亚洲国产精品久久人人爱蜜臀| 亚洲精品乱码久久久久久| 一区二区高清在线观看| 香蕉久久a毛片| 久久夜色精品| 国产精品盗摄久久久| 国产视频欧美视频| 最近看过的日韩成人| 国产精品99久久久久久人| 欧美一区中文字幕| 欧美成人一区二区三区在线观看 | 亚洲破处大片| 在线亚洲欧美| 久久国产婷婷国产香蕉| 欧美国产日韩亚洲一区| 国产乱码精品一区二区三区五月婷 | 有坂深雪在线一区| 亚洲午夜影视影院在线观看| 久久久国产精彩视频美女艺术照福利 | 在线观看亚洲一区| 亚洲天堂成人| 美日韩丰满少妇在线观看| 99re66热这里只有精品4| 久久av资源网站| 欧美视频日韩| 亚洲国产成人高清精品| 亚洲欧美日韩在线一区| 欧美成人资源| 欧美一区二区三区四区在线观看地址 | 久久久久看片| 一区二区av在线| 免费成人黄色片| 国精产品99永久一区一区| 亚洲一区二区三区中文字幕| 欧美大片第1页|