Okay! For future review and sharing with you! I will repeat the introduction in the book here.
Basic concepts:
An AC automatic machine is a special automatic machine. It is composed of some additional edges added to the tires tree. Its core part is the construction of suffix nodes.
Algorithm:
The construction of the AC automatic machine is divided into two steps. First, the tire tree is created through all the mode strings, and then the suffix nodes of each node are calculated from the root of the tree.
The process of creating the suffix of the AC automatic machine is very similar to that of the next array in the KMP algorithm. Here we also use the next array to represent the label of the next node corresponding to node I, fa [I] indicates the parent node of node I on the tire tree.
The character on the side from Fa [I] To I is C. The core idea is to first check whether next [Fa [I] has a character that is also a C side. If yes, next [I] is the subnode pointed to by next [Fa [I] marking the side of C. Otherwise, continue
Check the next [next [Fa [I] node. If the node that meets the condition still cannot be found through the continuous next, it indicates that there is no string on the tire and the path string of node I is the same as a string suffix, then its suffix
The node is the root,
Find the pseudocode of next:
Line up root runners
Next [root] <-(-1 );
While (queue is not empty ){
X <-The frontend is displayed.
For (X indicates the son of C I ){
TMP <-next [x]
While (TMP! =-1 and TMP does not contain the son labeled as c) TMP <-next [TMP];
If (TMP =-1) next [I] <-root;
Else next [I] <-TMP indicates the node pointed to by the side marked as C.
Push I into the queue
}
}
The traversal of the AC automatic machine is similar to the number of tire. The traversal of the Main string S is roughly as follows:
(1) Check every character C in s from the root node from the beginning to the back.
(2) If the current node X contains an edge marked as C, it moves along the edge to the next node.
(3) Otherwise, check the suffix node next [x] of X.
If next [x] contains an edge marked as C, it goes along this edge to the node pointed to by the edge marked as C in next [X.
If next [x] does not contain any side marked as C, continue to view the suffix node next [next [x] of next [X]. if the root node cannot be found. Move the root node.
(4) If there are still characters, return to (2 ).
To understand this image.
It's almost the same as writing so much.
Hdu2222. The Code is as follows:
#include<cstdio>#include<cstring>#define Max 500001using namespace std;char st[Max*2];int head,tail;struct node{node *next[26];node *fail;int cnt;node(){cnt=0;fail=NULL;memset(next,NULL,sizeof(next));}}*Q[Max];inline void insert(node *root){node *p=root;int i=0,idx;while(st[i]){idx=st[i]-'a';if(p->next[idx]==NULL) p->next[idx]=new node;p=p->next[idx];i++;}p->cnt++;}void built(node *root){root->fail=NULL;Q[head++]=root;while(head!=tail){node* tmp=Q[tail++];node* p=NULL;for(int i=0;i<26;i++){if(tmp->next[i]!=NULL){if(tmp==root) tmp->next[i]->fail=root;else{p=tmp->fail;while(p!=NULL){if(p->next[i]!=NULL){tmp->next[i]->fail=p->next[i];break;}p=p->fail;}if(p==NULL) tmp->next[i]->fail=root;}Q[head++]=tmp->next[i];}}}}int query(node *root){int i=0,res=0,idx;node *p=root;while(st[i]){idx=st[i]-'a';while(p->next[idx]==NULL&&p!=root) p=p->fail;p=p->next[idx];p=(p==NULL)?root:p;node *tmp=p;while(tmp!=root&&tmp->cnt!=-1){res+=tmp->cnt;tmp->cnt=-1;tmp=tmp->fail;}i++;}return res;}int main(){int n,t;scanf("%d",&t);while(t--){head=tail=0;node *root=new node;scanf("%d",&n);while(n--){scanf("%s",st);insert(root);}built(root);scanf("%s",st);printf("%d\n",query(root));}return 0;}