您的位置:首页 > 其它

ac自动机 hdu 2222

2014-12-01 21:56 253 查看
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <queue>

using namespace std;

struct node
{
node *fail;
node *next[26];
int Count;
node()
{
fail=NULL;
Count=0;
for( int i=0;i<26;i++ )
next[i]=NULL;
}
};
node *root;
char str[1000005];
queue<node*>q;

void update()//字典树
{
node *p=root;
int i=0,index;
while( str[i] )
{
index=str[i]-'a';
if( p->next[index]==NULL )
p->next[index]=new node;//new node()
p=p->next[index];
i++;
}
p->Count++;
}

void buildac()  //原理相当于获得kmp中的next数组
{
q.push( root );
while( !q.empty() )
{
node *p=NULL;
node *temp=q.front();
q.pop();
for( int i=0;i<26;i++ )
if( temp->next[i]!=NULL )
{
if( temp==root ) //j==-1
temp->next[i]->fail=root;
else
{
p=temp->fail;
while( p )
{
if( p->next[i] )
{
temp->next[i]->fail=p->next[i];//temp和temp->fail是同一个字母,如果temp->next[i]和temp->fail->next[i]都存在,则temp->next[i]->fail=temp->fail-next[i]
break;
}
p=p->fail;//j=next[j]
}
if( !p )//j==-1
temp->next[i]->fail=root;
}
q.push( temp->next[i] );
}
}
}

int Search()
{
int i=0,cut=0,index,len=strlen( str );
node *p=root;
while( str[i] )
{
index=str[i]-'a';
while( !p->next[index] && p!=root )//通过失败指针找到p->next[index]的存在,相当于kmp中j=next[j];
p=p->fail;
p=p->next[index];
p=( p==NULL )?root:p;//如果p==NULL, 说明此字母找不到匹配,p=root;相当于kmp中j=0,开始重新匹配
node *temp=p;
while( temp!=root && temp->Count!=-1 )//比如:在模式串she中找she、he,查找时肯定先找到she,然后用失败指针找he的存在http://img.blog.csdn.net/20141201215700044
{
cut+=temp->Count;
temp->Count=-1;
temp=temp->fail;
}
i++;
}
return cut;
}

int main()
{
int t, n;

scanf( "%d", &t );
while( t-- )
{
root=new node;
scanf( "%d", &n );
for( int i=0;i<n;i++ )
{
scanf( "%s", str );
update();
}
buildac();
scanf( "%s", str );
printf( "%d\n", Search() );
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: