您的位置:首页 > 其它

hdu2222 AC自动机

2015-05-18 01:24 141 查看
hdu2222:

题意:给出多个字符串(模式串),再给出一个待匹配串,问模式串中出现多少待匹配串

首先,一般的坑点:①待模式串可以相同,但是算多个模式串,需要重复计算 ②待匹配串中可以重复出现多次同一个模式串,但是这些重复出现不计入总匹配串数

但事实上,我一开始就并没有被这些迷惑,只是我使用的AC自动机模板并不是非常先进```中间有一处错误,是将所有以字典树上某串为原串或该串的后缀串为原串的总个数都累加到该串上,然后计算的时候加上该串的值即可。但是我wa了一发后很快发现此时只清除了该串的结尾个数,后面再匹配到其后缀串又会有重复计数的情况,然后我在加和之后再清除其所有后缀串的个数,但是仍然是wa,虽然并不清楚到底此处为什么wa,但是改为建树建nxt和fail时不加和,而匹配到时循环回去加就AC了```

果然太弱了连怎么WA的都不知道昂```

#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
const int maxm=500006;

char s[1000010],word[55];
int nxt[maxm][26],cnt[maxm],fail[maxm],size;

int newnode(){
memset(nxt[size],0,sizeof(nxt[size]));
fail[size]=cnt[size]=0;
return size++;
}

void insert(char s[]){
int i,p=0;
for(i=0;s[i];i++){
int &x=nxt[p][s[i]-'a'];
p=x?x:x=newnode();
}
cnt[p]++;
}

void makenxt(){
int i;
queue<int>q;
q.push(0);
while(!q.empty()){
int u=q.front();
q.pop();
for(i=0;i<26;i++){
int v=nxt[u][i];
if(v==0)nxt[u][i]=nxt[fail[u]][i];
else q.push(v);
if(u&&v){
fail[v]=nxt[fail[u]][i];
}
}
}
}

int query(char s[]){
int ans=0,d=0;
for(int i=0;s[i];i++){
d=nxt[d][s[i]-'a'];
int tmp=d;
while(tmp!=0){
ans+=cnt[tmp];
cnt[tmp]=0;
tmp=fail[tmp];
}
}
return ans;
}

int main(){
int T;
scanf("%d",&T);
while(T--){
int n;
size=0,newnode();
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%s",word);
insert(word);
}
makenxt();
scanf("%s",s);
printf("%d\n",query(s));
}
return 0;
}


hdu2222
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: