推荐博客:http://www.cnblogs.com/kuangbin/p/3164106.html AC自动机小结
https://blog.csdn.net/creatorx/article/details/71100840 AC自动机最详细的解释
1.(HDOJ2222)http://acm.hdu.edu.cn/showproblem.php?pid=2222
题意:求目标串中出现了几个模式串。
分析:AC自动机模板题
1 #include<cstdio> 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<queue> 6 using namespace std; 7 const int maxn=500010; 8 9 struct Trie 10 { 11 int nxt[maxn][26],fail[maxn],end[maxn]; //nxt为字典树, fail相当于kmp中的nxt数组, end对单词结尾做标记 12 int root,L; //L相当于字典树中的sz ,root为根节点(即;0) 13 int newnode() //初相当于始化一个字典树上的节点 14 { 15 for ( int i=0;i<26;i++ ) nxt[L][i]=-1; 16 end[L++]=0; 17 return L-1; 18 } 19 void init() 20 { 21 L=0; 22 root=newnode(); 23 } 24 void insert(char buf[]) //大致于字典树插入过程相同 25 { 26 int len=strlen(buf); 27 int now=root; 28 for ( int i=0;i<len;i++ ) 29 { 30 int x=buf[i]-‘a‘; 31 if ( nxt[now][x]==-1 ) nxt[now][x]=newnode(); 32 now=nxt[now][x]; 33 } 34 end[now]++; //在单词结尾处做标记 35 } 36 void build() //相当于kmp的操作 37 { 38 queue<int>que; 39 fail[root]=root; //根节点初始化为0(即其本身) 40 for (int i=0;i<26;i++ ) 41 { 42 if ( nxt[root][i]==-1 ) nxt[root][i]=root; 43 else //Trie中已经构建的节点 44 { 45 int x=nxt[root][i]; 46 fail[x]=root; 47 que.push(x); 48 } 49 } 50 while ( !que.empty() ) 51 { 52 int now=que.front(); 53 que.pop(); 54 for ( int i=0;i<26;i++ ) 55 { 56 if ( nxt[now][i]==-1 ) //无后继点 57 nxt[now][i]=nxt[fail[now]][i];//类似于kmp中求nxt数组一样 58 else //存在下一个节点 59 { 60 int x=nxt[now][i]; 61 fail[x]=nxt[fail[now]][i];//失配指针指向他父节点的失配指针的下一个相同字符处 62 que.push(x); 63 } 64 } 65 } 66 } 67 int query(char buf[]) //相当于字典树中的访问操作 68 { 69 int len=strlen(buf); 70 int now=root; 71 int res=0; 72 for ( int i=0;i<len;i++ ) 73 //沿着整个文本串移动,每移动到一个字符(节点) 时,通过失配指针不断找寻模式串 ,重点为源头,找到一个就将其标记清除 74 { 75 now=nxt[now][buf[i]-‘a‘]; 76 int tmp=now; 77 while ( tmp!=root ) 78 { 79 res+=end[tmp]; 80 end[tmp]=0; 81 tmp=fail[tmp]; 82 } 83 } 84 return res; //返回单词个数 85 } 86 void debug() 87 { 88 for ( int i=0;i<L;i++ ) 89 { 90 printf("%id=%3d,fail=%3d,end=%3d,chi=[",i,fail[i],end[i]); 91 for ( int j=0;j<26;j++ ) printf("%2d",nxt[i][j]); 92 printf("]\n"); 93 } 94 } 95 }; 96 char buf[maxn*2]; 97 Trie ac; 98 int main() 99 { 100 int T,n; 101 scanf("%d",&T); 102 while ( T-- ) 103 { 104 scanf("%d",&n); 105 ac.init(); 106 for ( int i=0;i<n;i++ ) 107 { 108 scanf("%s",buf); 109 ac.insert(buf); 110 } 111 ac.build(); 112 scanf("%s",buf); 113 printf("%d\n",ac.query(buf)); 114 } 115 return 0; 116 }
AC自动机模板(含解释)
1 #include<cstdio> 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<queue> 6 using namespace std; 7 const int maxn=500010; 8 9 struct Trie 10 { 11 int nxt[maxn][26],fail[maxn],end[maxn]; 12 int root,L; 13 int newnode() 14 { 15 for ( int i=0;i<26;i++ ) nxt[L][i]=-1; 16 end[L++]=0; 17 return L-1; 18 } 19 void init() 20 { 21 L=0; 22 root=newnode(); 23 memset(end,0,sizeof(end)); 24 } 25 void insert(char buf[]) 26 { 27 int len=strlen(buf); 28 int now=root; 29 for ( int i=0;i<len;i++ ) 30 { 31 int x=buf[i]-‘a‘; 32 if ( nxt[now][x]==-1 ) nxt[now][x]=newnode(); 33 now=nxt[now][x]; 34 } 35 end[now]++; 36 } 37 void build() 38 { 39 queue<int>que; 40 fail[root]=root; 41 for (int i=0;i<26;i++ ) 42 { 43 if ( nxt[root][i]==-1 ) nxt[root][i]=root; 44 else 45 { 46 int x=nxt[root][i]; 47 fail[x]=root; 48 que.push(x); 49 } 50 } 51 while ( !que.empty() ) 52 { 53 int now=que.front(); 54 que.pop(); 55 for ( int i=0;i<26;i++ ) 56 { 57 if ( nxt[now][i]==-1 ) 58 nxt[now][i]=nxt[fail[now]][i]; 59 else 60 { 61 int x=nxt[now][i]; 62 fail[x]=nxt[fail[now]][i]; 63 que.push(x); 64 } 65 } 66 } 67 } 68 int query(char buf[]) 69 { 70 int len=strlen(buf); 71 int now=root; 72 int res=0; 73 for ( int i=0;i<len;i++ ) 74 { 75 now=nxt[now][buf[i]-‘a‘]; 76 int tmp=now; 77 while ( tmp!=root ) 78 { 79 res+=end[tmp]; 80 end[tmp]=0; 81 tmp=fail[tmp]; 82 } 83 } 84 return res; 85 } 86 void debug() 87 { 88 for ( int i=0;i<L;i++ ) 89 { 90 printf("%id=%3d,fail=%3d,end=%3d,chi=[",i,fail[i],end[i]); 91 for ( int j=0;j<26;j++ ) printf("%2d",nxt[i][j]); 92 printf("]\n"); 93 } 94 } 95 }; 96 char buf[maxn*2]; 97 Trie ac; 98 int main() 99 { 100 int T,n; 101 scanf("%d",&T); 102 while ( T-- ) 103 { 104 scanf("%d",&n); 105 ac.init(); 106 for ( int i=0;i<n;i++ ) 107 { 108 scanf("%s",buf); 109 ac.insert(buf); 110 } 111 ac.build(); 112 scanf("%s",buf); 113 printf("%d\n",ac.query(buf)); 114 } 115 return 0; 116 }
HDOJ2222
原文地址:https://www.cnblogs.com/HDUjackyan/p/9043255.html
时间: 2024-10-15 20:39:30