您的位置:首页 > 其它

Keywords Search(查找关键字)

2011-08-30 21:55 267 查看

hdoj 2222


题目大意:给出一些字符串 ,再给出一段文字,问文字中出现多少个单词

解决:AC自动机

#include <iostream>
#include <cstring>
#include <queue>
#include <cstdio>
using namespace std;
#define s  scanf
int top;
struct node
{
int cnt;
int fail;
int next[26];
};
node tree[400000];
char mai[1000005];
void init()
{
top=1;
memset(tree[0].next,0,sizeof(tree[0].next));
//刚开始的时候初始化,是在node的构造函数中实现的,但是由于是多组测试数据,所以
//错误了好几次这次,就应该在初始化,和需要新的结点的时候在初始化
tree[top].cnt=0;
}
void insert_trie(char str[])
{
int id,i=0;
while(*str)
{
id=*str-'a';
if(!tree[i].next[id])
{
tree[i].next[id]=top;
memset(tree[top].next,0,sizeof(tree[top].next));
tree[top].cnt=0;
top++;
}
i=tree[i].next[id];
str++;
}
tree[i].cnt++;
}
void build_fail()
{
tree[0].fail=-1;
queue<int> q;
q.push(0);
while(!q.empty())
{
int now=q.front();
q.pop();
for(int i=0;i<26;i++)
{
int tmp=tree[now].next[i];
if(tmp)
{
int p;
for(p=tree[now].fail;p!=-1;p=tree[p].fail)
if(tree[p].next[i])
{
tree[tmp].fail=tree[p].next[i];
break;
}

if(p==-1){tree[tmp].fail=0;}
q.push(tmp);
}
}
}
}
void query(char str[])
{
int id,sum=0,p=0;
while(*str)
{
id=*str-'a';
//不匹配的情况,找到根节点,或者是找到匹配的地方
while(tree[p].next[id]==0 && p)p=tree[p].fail;
if(tree[p].next[id]==0)p=0;
else p=tree[p].next[id];
//匹配或者是根节点的情况,沿着fail一直找到跟,将所有的一该字母结束的串的情况 都   算上。
int tmp=p;
while(tmp && tree[tmp].cnt)
{
sum+=tree[tmp].cnt;
tree[tmp].cnt=0;
tmp=tree[tmp].fail;
}
str++;
}
printf("%d\n",sum);
}

int main()
{
int icase;
s("%d",&icase);
while(icase--)
{
init();
int n;
char str[60];
s("%d",&n);
while(n--)
{
s("%s",str);
insert_trie(str);
}
build_fail();
s("%s",mai);
query(mai);
}
//   system("pause");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: