码迷,mamicode.com
首页 > 其他好文 > 详细

hdu 2222 AC自动机学校

时间:2017-09-15 16:33:07      阅读:168      评论:0      收藏:0      [点我收藏+]

标签:pen   clu   ac自动机   ace   return   shu   stdio.h   static   open   

#include <iostream>
#include <stdio.h>
#include <queue>
using namespace std;
const int maxn=(int)1e6+10;
const int maxm=(int)5e5+10;
struct trie{
int nxt[maxm][26],fail[maxm],ed[maxm];
int rt,l;
int newnod(){
for(int i=0;i<26;i++)nxt[l][i]=-1;
ed[l++]=0;
return l-1;
}
void init(){
l=0;rt=newnod();
}
void inset(char s[]){
int now=rt;
for(int i=0;s[i];i++){
if(nxt[now][s[i]-‘a‘]==-1)nxt[now][s[i]-‘a‘]=newnod();
now=nxt[now][s[i]-‘a‘];
}
ed[now]++;
}
void build(){
static queue<int>q;fail[rt]=rt;

for(int i=0;i<26;i++)
if(nxt[rt][i]==-1)nxt[rt][i]=rt;
else{
fail[nxt[rt][i]]=rt;q.push(nxt[rt][i]);
}
while(!q.empty()){
int now=q.front();
q.pop();
for(int i=0;i<26;i++){
if(nxt[now][i]==-1) nxt[now][i]=nxt[fail[now]][i];
//如果当前单词的下一个字母结点为空,当前单词的该字母结点指
//向fail结点的对应字母结点
else{
//如果当前单词的下一个字母结点不为空,当前单词的该字母结点的fail结点
//指向fail结点的对应字母结点
fail[nxt[now][i]]=nxt[fail[now]][i];
q.push(nxt[now][i]);
}
}
}
}
//fail[i]即i结点所在单词以i结点为结尾和其它单词中以i结点代表字母为结尾的公共最长后前缀的结点
int query(char s[]){
int now=rt,res=0;
for(int i=0;s[i];i++){
now=nxt[now][s[i]-‘a‘];
//新start=上一个start的s[i]字母结点的nxt指向结点,单词存在就指向单词下一个字母,
//不存在指向别的单词的该字母,就指向fail[st]的nxt指向结点
//
int tmp=now;
printf("s[%d]: %c tmp :%d now:%d\n",i,s[i],tmp,now);
while(tmp!=rt){

if(ed[tmp]==1)printf("--%d\n",tmp);
res+=ed[tmp];ed[tmp]=0;tmp=fail[tmp];
printf("tmp:%d\n",tmp);
}
}
return res;
}
void debug(){
printf("id = %3d fail = %3d ed= %3d chi = [",0,0,0);
for(int j=0;j<26;j++)printf("%2c",‘a‘+j);printf("\n");
for(int i=0;i<l;i++){
printf("id = %3d fail = %3d ed= %3d chi = [",i,fail[i],ed[i]);
for(int j=0;j<26;j++)printf("%2d",nxt[i][j]);printf("\n");
}
}

};
char s[maxn];
trie ac;

void dfs(int st,string tmp=""){
if(ac.ed[st]!=0) cout<<tmp<<endl;
for(int i=0;i<26;i++){
if(ac.nxt[st][i]!=-1) dfs(ac.nxt[st][i],tmp+(char)(‘a‘+i));
}
}
void dfs1(int st,string tmp=""){
if(ac.ed[st]!=0) cout<<tmp<<endl;
for(int i=0;i<26;i++){
if(ac.nxt[st][i]!=0) dfs(ac.nxt[st][i],tmp+(char)(‘a‘+i));
}
}
int main()
{
#ifdef shuaishuai
freopen("C:\\Users\\hasee\\Desktop\\a.txt","r",stdin);
//freopen("C:\\Users\\hasee\\Desktop\\b.txt","w",stdout);
#endif
int T,n;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
ac.init();
for(int i=0;i<n;i++){
scanf("%s",s);
ac.inset(s);
}

// dfs(0);
ac.debug();
ac.build();
// dfs1(0);
// for(int i=0;i<ac.l;i++)
// { printf("%d\n",ac.ed[i]);
// for(int j=0;j<26;j++)printf("%d ",ac.nxt[i][j]);
// printf("\n");
// }
ac.debug();
scanf("%s",s);
printf("%d\n",ac.query(s));
}
return 0;
}

hdu 2222 AC自动机学校

标签:pen   clu   ac自动机   ace   return   shu   stdio.h   static   open   

原文地址:http://www.cnblogs.com/MeowMeowMeow/p/7526649.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!