http://acm.hdu.edu.cn/showproblem.php?pid=2896
题意:给你N个匹配串和M个模式串, 问你每个模式串中,N个匹配串有哪些出现过。
思路:AC自动机,和hdu2222思路其实是一样的,只不过这里就是需要增加一个域,来标记以该结点结束的串
#include<stdio.h>
#include<string.h>
const int MAXN = 200*500+10 ;
int N , M ;
char name[210] ;
struct Node{
int num ; //标记这个单词的标号
int f ; //表示是否是一个单词的结束
Node *fail ;
Node *next[128] ;
Node(){
num = 0 ;
f = 0 ;
fail = NULL ;
memset(next, 0 , sizeof(next));
}
}*root ;
int front, rear ;
Node *que[MAXN] ;
char str[10010] ;
void build_trie(char *ch , int num){
Node *loc = root ,*q;
int idx ;
for(int i=0;ch[i]!=0;i++){
idx = ch[i] ;
if(loc->next[idx] == NULL){
q = new Node ;
loc->next[idx] = q ;
}
loc = loc->next[idx] ;
}
loc->f = 1 ;
loc->num = num ;
}
void build_automation(){
front = rear = 0 ;
Node *temp ,*q ;
root->fail = NULL ;
que[rear++] = root ;
while(front != rear){
temp = que[front++] ;
for(int i=0;i<128;i++){
if(temp->next[i] == NULL) continue ;
if(temp == root){
temp->next[i]->fail = root ;
}
else{
q = temp->fail;
while(q != NULL){
if(q->next[i] != NULL){
temp->next[i]->fail = q->next[i] ;
break ;
}
q = q->fail;
}
if(q == NULL)
temp->next[i]->fail = root ;
}
que[rear++] = temp->next[i] ;
}
}
}
bool one[510] ;
void query(char *ch){
Node *loc = root ,*q;
int idx;
for(int i=0;ch[i]!=0;i++){
idx = str[i] ;
while(loc!=root && loc->next[idx]==NULL) loc=loc->fail;
loc = loc->next[idx] ;
if(loc == NULL){
loc = root ;
}
q = loc ;
while(q != root){
if(q->f){
one[ q->num] = 1 ;
}
q = q->fail;
}
}
}
int main(){
while(scanf("%d",&N) == 1){
root = new Node ;
for(int i=1;i<=N;i++){
scanf("%s",name);
build_trie(name , i) ;
}
build_automation();
scanf("%d",&M);
int res = 0 ;
for(int i=1;i<=M;i++){
scanf("%s",str);
memset(one , 0 , sizeof(one));
query(str);
bool have = 0 ;
for(int j=1;j<=N;j++){
if( one[j] ){
have = 1 ; break ;
}
}
if(have){
res++ ;
printf("web %d:",i);
for(int j=1;j<=N;j++){
if( one[j] ) printf(" %d",j);
}
printf("\n");
}
}
printf("total: %d\n",res);
}
return 0 ;
}
的标号。
代码: