1. 程式人生 > >廣義後綴自動機模板

廣義後綴自動機模板

targe add 自動機 con 諸多 display memcpy urn 博客

後綴自動機能解決很多單串的問題、但是一旦到了多串的情況、可能就會變得有些棘手

這個時候你可能會想能不能將多個串一起構建出和單串後綴自動機那樣子擁有諸多優美性質的自動機呢?

答案當然是有的、那就是廣義後綴自動機

對於廣義後綴自動機、和普通的後綴自動機寫法上有些許不同之處

大致就是在插入新串的時候、需要把當前狀態指針 last 指回 root

還有一個問題、網上的人們都說廣義後綴自動機在新插入節點的時候要判是否已經存在

這個就造成了代碼的迥異

關於代碼、借鑒了這個博客 ==> Click here

下面僅僅給出模板

技術分享圖片
struct General_Suffix_Automaton{
    
static const int maxn = ((int)1e5 + 10) * 2; static const int Letter = 26; int fa[maxn]; int len[maxn]; int ch[maxn][Letter]; int cnt[maxn]; int tpSum[maxn]; int tp[maxn]; int tot; int last; int mxLen; inline void init(){ last = tot = 1
; len[1] = 0; mxLen = 0; memset(ch[1], 0, sizeof(ch[1])); memset(cnt, 0, sizeof(cnt)); } inline void add(int x){ int p = last; if(ch[p][x] && len[ch[p][x]] == len[p] + 1){ last = ch[p][x]; return ; }
///就是在這裏特判、下面的代碼就基本和普通的SAM差不多了 int np = ++tot; memset(ch[np], 0, sizeof(ch[np])); last = np; len[np] = len[p] + 1; while(p && !ch[p][x]) ch[p][x] = np, p = fa[p]; if(!p) fa[np] = 1; else{ int q = ch[p][x]; if(len[q] == len[p] + 1) fa[np] = q; else{ int nq = ++tot; len[nq] = len[p] + 1; memcpy(ch[nq], ch[q], sizeof(ch[q])); fa[nq] = fa[q]; fa[q] = fa[np] = nq; while(p && ch[p][x] == q) ch[p][x] = nq, p = fa[p]; } } } inline void addStr(char * s){ last = 1; int len = strlen(s); mxLen = max(mxLen, len); for(int i=0; i<len; i++) add(s[i] - a),cnt[last]++; } int deg[maxn]; inline void toposort(){ for(int i = 1; i <= mxLen; i++)tpSum[i] = 0; for(int i = 1; i <= tot; i++)tpSum[len[i]]++; for(int i = 1; i <= mxLen; i++)tpSum[i] += tpSum[i-1]; for(int i = 1; i <= tot; i++)tp[tpSum[len[i]]--] = i; for(int i = tot; i; i--)cnt[fa[tp[i]]] += cnt[tp[i]]; // 用下面的隊列來構造拓撲序也是可以的 // queue<int> que; // while(!que.empty()) que.pop(); // int tmp = tot; // for(int i=1; i<=tot; i++) deg[fa[i]]++; // for(int i=1; i<=tot; i++) if(!deg[i]) que.push(i); // while(!que.empty()){ // int x = que.front(); // que.pop(); // tp[tmp--] = x; // deg[fa[x]]--; // if(!deg[fa[x]]) que.push(fa[x]); // } // for(int i=tot; i>=1; i--) cnt[fa[tp[i]]] += cnt[tp[i]]; } inline void GetAns(char *s){ ///.... } }sam;
View Code

廣義後綴自動機模板