您的位置:首页 > 其它

HDU2222 Keywords Search [AC自动机]

2012-08-05 00:11 281 查看
  AC自动机的模版题,应该是很多人的AC自动机处女作吧。。

  在斌牛的讲解下,总算是对AC自动机了解了个大概,这里采用了AC自动机和Trie图两种写法,据说后者在AC自动机DP中用的比较多,应该很快就会做到了。。。两者差不多,Trie图利用失败指针来建图,据说AC自动机到Trie图就是转化成了确定性有穷自动机。

  贴一下两种写法的代码,当模版了。

 AC自动机:

#include <string.h>
#include <stdio.h>
#include <queue>
#define MAXS 500010

int cas,n;
char s[55],find[1000005];
int next[MAXS][26],pos,tot[MAXS],fail[MAXS];
int newnode(){
memset(next[pos],0,sizeof next[pos]);
tot[pos]=fail[pos]=0;
return pos++;
}
void insert(char *s){
int len=strlen(s);
int p=0;
for(int i=0;i<len;i++){
int k=s[i]-'a';
p=next[p][k]?next[p][k]:next[p][k]=newnode();
}
++tot[p];
}
void makefail(){
std::queue<int> q;
q.push(0);
while(!q.empty()){
int u=q.front();q.pop();
for(int i=0;i<26;i++){
int v=next[u][i];
if(v==0)continue;
q.push(v);
if(u==0)continue;
fail[v]=next[0][i];
for(int f=fail[u];f!=0;f=fail[f]){
if(next[f][i]){
fail[v]=next[f][i];
break;
}
}
}
}
}
int makeans(char *s){
int ans=0;
for(int i=0,p=0;s[i];i++){
int k=s[i]-'a';
while(p>0&&!next[p][k])p=fail[p];
p=next[p][k];
for(int t=p;t!=0;t=fail[t]){
if(tot[t]>=0){
ans+=tot[t];
tot[t]=-1;
}else break;
}
}
return ans;
}
int main(){
freopen("test.in","r",stdin);
scanf("%d",&cas);
for(int ca=1;ca<=cas;ca++){
scanf("%d",&n);
pos=0;newnode();
for(int i=1;i<=n;i++){
scanf("%s",s);
insert(s);
}
makefail();
scanf("%s",find);
int x=makeans(find);
printf("%d\n",x);
}
return 0;
}


Trie图:

#include <string.h>
#include <stdio.h>
#include <queue>
#define MAXS 500010

int cas,n;
char s[55],find[1000005];
int next[MAXS][26],pos,tot[MAXS],fail[MAXS];
int newnode(){
memset(next[pos],0,sizeof next[pos]);
tot[pos]=fail[pos]=0;
return pos++;
}
void insert(char *s){
int p=0;
for(int i=0;s[i];i++){
int k=s[i]-'a';
p=next[p][k]?next[p][k]:next[p][k]=newnode();
}
++tot[p];
}
void makefail(){
std::queue<int> q;
q.push(0);
while(!q.empty()){
int u=q.front();q.pop();
for(int i=0;i<26;i++){
int v=next[u][i];
if(v==0)next[u][i]=next[fail[u]][i];
else q.push(v);
if(v!=0&&u!=0)fail[v]=next[fail[u]][i];
}
}
}
int makeans(char *s){
int ans=0;
for(int i=0,p=0,j;s[i];i++){
int k=s[i]-'a';
p=next[p][k];
for(int j=p;j&&tot[j]!=-1;j=fail[j]){
ans+=tot[j];
tot[j]=-1;
}
}
return ans;
}
int main(){
freopen("test.in","r",stdin);
scanf("%d",&cas);
for(int ca=1;ca<=cas;ca++){
scanf("%d",&n);
pos=0;newnode();
for(int i=1;i<=n;i++){
scanf("%s",s);
insert(s);
}
makefail();
scanf("%s",find);
int x=makeans(find);
printf("%d\n",x);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: