hdu 2222(AC自动机)
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn = 1e7 + 5; 4 const int MAX = 10000000; 5 int cnt; 6 struct node{ 7 node *next[26]; 8 node *fail; 9 int sum; 10 }; 11 node *root; 12 char key[70]; 13 node *q[MAX]; 14 int head,tail; 15 node *newnode; 16 char pattern[maxn]; 17 int N; 18 void Insert(char *s) 19 { 20 node *p = root; 21 for(int i = 0; s[i]; i++) 22 { 23 int x = s[i] - 'a'; 24 if(p->next[x] == NULL) 25 { 26 newnode=(struct node *)malloc(sizeof(struct node)); 27 for(int j=0;j<26;j++) newnode->next[j] = 0; 28 newnode->sum = 0;newnode->fail = 0; 29 p->next[x]=newnode; 30 } 31 p = p->next[x]; 32 } 33 p->sum++; 34 } 35 void build_fail_pointer() 36 { 37 head = 0; 38 tail = 1; 39 q[head] = root; 40 node *p; 41 node *temp; 42 while(head < tail) 43 { 44 temp = q[head++]; 45 for(int i = 0; i <= 25; i++) 46 { 47 if(temp->next[i]) 48 { 49 if(temp == root) 50 { 51 temp->next[i]->fail = root; 52 } 53 else 54 { 55 p = temp->fail; 56 while(p) 57 { 58 if(p->next[i]) 59 { 60 temp->next[i]->fail = p->next[i]; 61 break; 62 } 63 p = p->fail; 64 } 65 if(p == NULL) temp->next[i]->fail = root; 66 } 67 q[tail++] = temp->next[i]; 68 } 69 } 70 } 71 } 72 void ac_automation(char *ch) 73 { 74 node *p = root; 75 int len = strlen(ch); 76 for(int i = 0; i < len; i++) 77 { 78 int x = ch[i] - 'a'; 79 while(!p->next[x] && p != root) p = p->fail; 80 p = p->next[x]; 81 if(!p) p = root; 82 node *temp = p; 83 while(temp != root) 84 { 85 if(temp->sum >= 0) 86 { 87 cnt += temp->sum; 88 temp->sum = -1; 89 } 90 else break; 91 temp = temp->fail; 92 } 93 } 94 } 95 int main() 96 { 97 int T; 98 scanf("%d",&T); 99 while(T--) 100 { 101 root=(struct node *)malloc(sizeof(struct node)); 102 for(int j=0;j<26;j++) root->next[j] = 0; 103 root->fail = 0; 104 root->sum = 0; 105 scanf("%d",&N); 106 for(int i = 1; i <= N; i++) 107 { 108 scanf("%s",key); 109 Insert(key); 110 } 111 scanf("%s",pattern); 112 cnt = 0; 113 build_fail_pointer(); 114 ac_automation(pattern); 115 printf("%d\n",cnt); 116 } 117 return 0; 118 }
大佬的博客:https://blog.csdn.net/creatorx/article/details/71100840
hdu6208
1 #include<stdio.h> 2 #include<string.h> 3 #include<queue> 4 #include<string> 5 #include<iostream> 6 const int maxn = 100005; 7 using namespace std; 8 9 int n; 10 int nxt[maxn][30],FAIL[maxn],edd[maxn],root,L; 11 int mark[maxn]; 12 13 int newnode() 14 { 15 for(int i=0;i<26;i++) 16 nxt[L][i] = -1;//节点连接的边初始化为-1 17 edd[L]=0; 18 mark[L]=0; 19 return L++; 20 } 21 22 void init() 23 { 24 L=0; 25 root=newnode(); 26 } 27 28 void insert(char buf[],int l)//trie树的建立 29 { 30 int now=root; 31 for(int i=0;i<l;i++) 32 { 33 if(nxt[now][buf[i]-'a']==-1) 34 nxt[now][buf[i]-'a']=newnode(); 35 now=nxt[now][buf[i]-'a']; 36 } 37 edd[now]++; 38 } 39 40 void build()//建立ac自动机 41 { 42 queue<int>que; 43 for(int i=0;i<26;i++) 44 { 45 if(nxt[root][i]==-1) 46 nxt[root][i]=root; 47 else //若有连边则将节点加入队列 ,并将FAIL指针指向root 48 { 49 FAIL[nxt[root][i]]=root; 50 que.push(nxt[root][i]); 51 } 52 } 53 while(!que.empty()) 54 { 55 int now=que.front(); 56 que.pop(); 57 for(int i=0;i<26;i++) 58 { 59 if(nxt[now][i]==-1) //若无连边,则将该边指向当前节点FAIL指针指向的相应字符连接的节点 60 nxt[now][i]=nxt[FAIL[now]][i]; 61 else //若有连边,则将儿子节点的FAIL指针指向当前节点FAIL指针指向相应字符接的节点 62 { 63 FAIL[nxt[now][i]]=nxt[FAIL[now]][i]; 64 que.push(nxt[now][i]); //加入队列继续遍历 65 } 66 } 67 } 68 } 69 70 int query(char buf[],int l) 71 { 72 int now=root; 73 int res=0; 74 for(int i=0;i<l;i++) 75 { 76 now=nxt[now][buf[i]-'a']; 77 int temp=now; 78 while(temp!=root&&mark[temp]==0)//根据题目要求改变形式 79 { 80 res+=edd[temp]; 81 edd[temp]=0; 82 mark[temp]=1; 83 temp=FAIL[temp]; 84 } 85 } 86 return res; //在这里返回的是匹配到的模式串的数量 87 } 88 89 char buf[maxn],ans[maxn]; 90 string A[maxn]; 91 92 int main() 93 { 94 int T; 95 scanf("%d",&T); 96 while(T--) 97 { 98 scanf("%d",&n); 99 init(); 100 int ma=0; 101 for(int i=0;i<n;i++) 102 { 103 scanf("%s",buf); 104 int l=strlen(buf); 105 if(ma<l) 106 { 107 ma=l; 108 strcpy(ans,buf); 109 } 110 insert(buf,l); 111 } 112 build(); 113 int sum = query(ans,ma); 114 if(sum == n) printf("%s\n", ans); 115 else puts("No"); 116 } 117 }