您的位置:首页 > 编程语言 > C语言/C++

Keywords Search(AC自动机)

2015-07-26 17:53 295 查看
A - Keywords Search
Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d
& %I64u
Submit Status

Description

In the modern time, Search engine came into the life of everybody like Google, Baidu, etc. 

Wiskey also wants to bring this feature to his image retrieval system. 

Every image have a long description, when users type some keywords to find the image, the system will match the keywords with description of image and show the image which the most keywords be matched. 

To simplify the problem, giving you a description of image, and some keywords, you should tell me how many keywords will be match. 

 

Input

First line will contain one integer means how many cases will follow by. 

Each case will contain two integers N means the number of keywords and N keywords follow. (N <= 10000) 

Each keyword will only contains characters 'a'-'z', and the length will be not longer than 50. 

The last line is the description, and the length will be not longer than 1000000. 

 

Output

Print how many keywords are contained in the description.
 

Sample Input

1
5
she
he
say
shr
her
yasherhs

 

Sample Output

3

 

bestcode:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<queue>

using namespace std;

const int MAX = 550000;

int kid[MAX][26],fail[MAX],v[MAX];

struct AcTrie
{
int rt,L;
//初始化
void Init(){L=0;rt=newnode();}
//新建节点
int newnode(){
v[L] = 0;
memset(kid[L],-1,sizeof(kid[L]));
return L++;
}
//建立trie树
void insert(char* s){
int now = rt;
for(int i=0;s[i];++i){
int t = s[i]-'a';
if(kid[now][t]==-1)
kid[now][t] = newnode();
now = kid[now][t];
}
v[now]++;
}
//建立trie图
void Build()
{
queue<int> q;
for(int i=0;i<26;++i){
if(kid[rt][i]==-1){
kid[rt][i] = rt;
}
else {
fail[kid[rt][i]] = rt;
q.push(kid[rt][i]);
}
}
while(!q.empty())
{
int now = q.front();q.pop();
for(int i=0;i<26;++i){
if(kid[now][i]==-1){
kid[now][i] = kid[fail[now]][i];
}
else {
fail[kid[now][i]] = kid[fail[now]][i];
q.push(kid[now][i]);
}
}
}
}
//查询
int query(char* s)
{
int ans = 0;
int now = rt,tmp;
for(int i=0;s[i];++i){
int t = s[i]-'a';
now = tmp = kid[now][t];
while(tmp!=rt)
{
ans += v[tmp];
v[tmp] = 0;
tmp = fail[tmp];
}
}
return ans;
}
}ac;

char str[1000000+50];

int main()
{
#ifdef zsc
freopen("input.txt","r",stdin);
#endif
int n,m,i,j,k;

scanf("%d",&n);
while(n--)
{
ac.Init();
scanf("%d",&m);
while(m--)
{
scanf("%s",str);
ac.insert(str);
}
ac.Build();
scanf("%s",str);
printf("%d\n",ac.query(str));
}
return 0;
}


AC代码:

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<queue>
using namespace std;
const int MAX = 550000;
struct trie
{
int root,L;
int kid[MAX][26],fail[MAX],v[MAX];
trie()
{
L = 0;
root =newnote();
}
int newnote();
void build();
void insert(string str);
int query(string str);
}*ac;
int trie::newnote()
{
v[L]=0;
memset(kid[L],-1,sizeof(kid[L]));
return L++;
}
void trie::build()
{
int i,now;
queue<int> p;
for(i=0;i<26;++i)
{
if(kid[root][i]==-1)
{
kid[root][i] = root;
}
else
{
fail[kid[root][i]] = root;
p.push(kid[root][i]);
}
}
while(!p.empty())
{
now = p.front();p.pop();
for(i=0;i<26;++i)
{
if(kid[now][i]==-1)
kid[now][i] = kid[fail[now]][i];
else
{
fail[kid[now][i]] = kid[fail[now]][i];
p.push(kid[now][i]);
}
}
}
}
void trie::insert(string str)
{
int now = root;
for(int i=0;str[i];++i)
{
int d = str[i] - 'a';
if(kid[now][d] == -1)
{
kid[now][d] = newnote();
}
now = kid[now][d];
}
v[now]++;
}
int trie::query(string str)
{
int tmp,now,res=0,i;
now = root;
for(i=0;str[i];++i)
{
tmp = now = kid[now][str[i]-'a'];
while(root!=tmp)
{
res+=v[tmp];
v[tmp]=0;
tmp = fail[tmp];
}
}
return res;
}
int main()
{
/*freopen("input.txt","r",stdin);*/
int n,m;
string str;
cin >> n;
while(n--)
{
ac = new trie;
cin >> m;
while(m--)
{
cin >> str;
ac->insert(str);
}
ac->build();
cin >> str;
cout << ac->query(str) << endl;
delete ac;
}
return 0;
}


注释代码&&模板:

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<queue>
using namespace std;
const int MAX = 55;
struct actrie
{
int root,L;//根节点,节点数
int kid[MAX][26],fail[MAX],v[MAX];
//孩子节点,失败返回,单串的最后位置数
int newnote();//初始化字典树
actrie()
{
L=0;root=newnote();
}
void build();//建立fail数组
int query(string st);//查找函数
void insert(string str);//插入函数
}ac;
int actrie::newnote()
{
v[L]=0;
memset(kid[L],-1,sizeof(kid[L]));
return L++;
}
void actrie::build()
{
queue<int> p;
fail[root] = root;
for(int i=0;i<26;++i)
{
if(kid[root][i]==-1)//不存在的
kid[root][i]=root;
else
{
fail[kid[root][i]] = root;//储存失败后的节点
p.push(kid[root][i]);
}
}
while(!p.empty())
{
int now = p.front();p.pop();
for(int i=0;i<26;++i)
{
if(kid[now][i]==-1)
kid[now][i] = kid[fail[now]][i];
else
{
fail[kid[now][i]] = kid[fail[now]][i];
p.push(kid[now][i]);
}
}
}
}
void actrie::insert(string str)
{
int now = root;
for(int i=0;str[i];++i)
{
int d = str[i] - 'a';
if(kid[now][d]==-1)
{
kid[now][d] = newnote();
}
now = kid[now][d];
}
v[now]++;//在字符串最后加1,证明存在这样的字符串
}
int actrie::query(string st)
{
int res=0;
int now = root,tmp;
for(int i=0;st[i];++i)
{
tmp = now = kid[now][st[i]-'a'];
while(tmp!=root)
//每个节点都是不同的,相当于一棵树中的节点位置。当搜索完成了,就全部在根节点
{
res+=v[tmp];//找到了匹配串,因为一开始已经规定了哪几个串,所以只有串尾有数值
v[tmp] = 0;
tmp = fail[tmp];
}
}
return res;
}
int main()
{
int n,m,i;
string str[10010],st;
cin >> n;
while(n--)
{
cin >> m;
for(i=0;i<m;++i)
{
cin >> str[i];
ac.insert(str[i]);
}
ac.build();
cin >> st;
cout << ac.query(st) << endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  字典树 c++