HDU 2222 AC自动机模板题
1、HDU 2222
2、题意:给出n个单词,一个字串,求有多少个单词在字串里出现了。注意给出的单词可能会重复,重复的不计。
3、总结:入门题。在查询这里还是不太懂。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
// 2222 #include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define F(i,a,b) for (int i=a;i<b;i++) #define FF(i,a,b) for (int i=a;i<=b;i++) #define mes(a,b) memset(a,b,sizeof(a)) #define INF 0x3f3f3f3f typedef long long ll; const int N = 1e6+10; struct node { int count; node *next[26]; node *fail; void init() { //初始化 mes(next,NULL); count=0; fail=NULL; } }*q[500010]; node *root; int head,tail; char str[N]; void insert(char *keyword) { int len=strlen(keyword); node *p=root; for(int i=0; i<len; i++) { int index=keyword[i]-'a'; if(p->next[index]==NULL) p->next[index]=new node(); //注:这里要new申请内存,不要忘了 p=p->next[index]; } p->count++; } void build_ac_automation() //初始化fail指针,BFS { q[tail++]=root; while(head!=tail) { node *p=q[head++]; //弹出队头 node *temp=NULL; for(int i=0; i<26; i++) { if(p->next[i]!=NULL) { if(p==root) p->next[i]->fail=root; //第一个元素fail必指向根 else { temp=p->fail; while(temp) { //2种情况结束:匹配为空or找到匹配 if(temp->next[i]) { //找到匹配 p->next[i]->fail=temp->next[i]; break; } temp=temp->fail; } if(!temp) p->next[i]->fail=root; //为空则从头匹配 } q[tail++]=p->next[i]; //入队 } } } } void query() //扫描,查询这里还是没太搞懂 { int i=0,cnt=0,index,len=strlen(str); node *p=root; for(int i=0; str[i]; i++) { index=str[i]-'a'; while(p->next[index]==NULL&&p!=root) p=p->fail; //跳转失败指针 p=p->next[index]; if(p==NULL) p=root; node *temp=p; //p即是找到的当前结点,p不动,temp计算后缀串 while(temp!=root&&temp->count!=-1) { cnt+=temp->count; temp->count=-1; temp=temp->fail; } } printf("%d\n", cnt); } int main() { int T,n; char keyword[100]; scanf("%d", &T); while(T--) { head=tail=0; scanf("%d", &n); getchar(); root=new node(); while(n--) { gets(keyword); insert(keyword); } build_ac_automation(); gets(str); query(); } return 0; }