參考連結:http://blog.sina.com.cn/s/blog_7812e98601012cim.html
尾碼自動機和尾碼數組一樣,剛開始學的時候十分不好懂,學完之後覺得自己很厲害了,然後拿到題目就傻眼了
對於字串這裡的很多演算法的性質都一樣,如果不能完全理解其構造的意義,那麼是根本做不了題目的,例如KMP
演算法,開始學習的時候next函數是用來匹配用的,後來發現基本上考KMP的題目根本不會涉及到匹配,每次都是
根據next值來判斷串具有的性質,所以對next值不理解就無法做題,同樣尾碼數組,沒有題目會叫你輸出sa數組
或者rank數組的值的,都會讓你根據這兩個數組的值,來構造一個其他的什麼東西,然後解題,比如說height數組
這裡也一樣,構造一個尾碼自動機也不能說明你對這個演算法很熟悉,只能說明,你知道有這麼個演算法!
表示目前對尾碼自動機理解有限
尾碼自動機的闡述以及構造方法上面的串連已經說明的很清楚了,感謝那位博主的分享
下面我闡述一下我學習過程中對遇到問題的理解:
1、為什麼當len=len+1的時候直接就處理,不是的時候要copy出來
如果是的話,那麼說明這個節點只能有上面一個節點過來,在尾碼自動機中一個兒子可以有多個父親
len表示的從根節點到這個位置的最長路徑,如果目前這個父親個他的兒子相差一個,表示這個兒子
只能由這一個父親過來,否則就不是,不是的話如果直接處理就會出現問題了
至於為什麼要copy出來,這個其實也不太好理解,copy出來,重新設定len值,然後把後面指向原來的
全部、指向這個剛copy出來的節點,這樣目的是
1、copy出來,防止直接處理漏掉很多尾碼
2、沿路將指向copy前的那個節點的可加尾碼的節點全部轉移到新的節點,目的是防止出現重複尾碼情況
說的很亂,因為還不是很理解
#include <iostream>#include <string.h>#include <stdio.h>#include <algorithm>using namespace std;#define maxn 10000char str[maxn];struct node{ node *next[26]; node *f; int len; node():len(0),f(0) { memset(next,0,sizeof(next)); }}re_root,*tail=&re_root;int build_suffix_array(char ch){ int temp=int(ch-'a'); node *p=new node(),*q=tail,*r; p->len=tail->len+1; for( ;q&&!q->next[temp];q=q->f) q->next[temp]=p; tail=p; if(q==NULL) tail->f=&re_root; else if(q->next[temp]->len==q->len+1) tail->f=q; else { r=new node(); *r=*(q->next[temp]); r->len=q->len+1; tail->f=r; p=q->next[temp]; p->f=r; for( ;q&&q->next[temp]==p;q=q->f) q->next[temp]=r; }return 0;}int pos;int triverse(node *root){ bool flag=true; for(int i=0;i<26;i++) { if(root->next[i]) { str[pos++]='a'+i; triverse(root->next[i]); pos--; flag=false; } } if(flag) { str[pos]=0; printf("%s\n",str); } return 0;}int main(){ int i,k,t; scanf("%s",str); for(i=0;str[i];i++) build_suffix_array(str[i]); printf("Ok\n"); pos=0; triverse(&re_root); return 0;}