对应HDU题目:点击打开链接
Time Limit: 1000MS | Memory Limit: 32768KB | 64bit IO Format: %I64d & %I64u |
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.
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.
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
题意:给出一些关键字,再给出一串字符,问哪些关键字在字符串中出现过,目测关键字可重复出现~
思路:AC自动机入门题
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#include<algorithm>
#include<cstring>
#include<string>
#include<iostream>
#define ms(x,y) memset(x,y,sizeof(x))
const int MAXN=1000000+10;
using namespace std;
char str[MAXN];
int ans;
struct Trie
{
Trie *next[26],*fail;
int cnt;
};
Trie *root;
void CreateTrie(char *s)//建字典树
{
Trie *p,*q;
p=root;
int len=strlen(s);
for(int i=0; i<len; i++){
int id=s[i]-'a';
if(p->next[id]==NULL){
q=(Trie*)malloc(sizeof(Trie));
q->cnt=0;
q->fail=NULL;
for(int j=0; j<26; j++) q->next[j]=NULL;
p->next[id]=q;
}
p=p->next[id];
}
p->cnt++;//巨坑!这里改++为=1就WA,即是关键字可重复算。。。
}
void CreateFail()//建立字典树的失败指针
{
int i;
Trie *now;
queue<Trie*>que;
que.push(root);
while(!que.empty())
{
now=que.front();
que.pop();
for(i=0; i<26; i++){
if(now->next[i]==NULL) continue;
if(now==root) now->next[i]->fail=root;//如当前节点为根节点,则子节点的失败指针都是root;
else{
Trie *tmp=now;//下面比较重要,按自己理解是:
//要求当前节点某ID子节点的失败指针,就得判断当前节点
//的失败指针所指的节点的该ID子节点是否为NULL
while(tmp->fail!=NULL)
{
if(tmp->fail->next[i]!=NULL){//不为NULL,直接指向它;
now->next[i]->fail=tmp->fail->next[i];
break;
}
tmp=tmp->fail;//沿着失败指针走
}
if(tmp->fail==NULL) now->next[i]->fail=root;//全部都为空,则指向root
}
que.push(now->next[i]);//入队
}
}
}
void FindTrie(char *s)
{
int i;
int len=strlen(s);
Trie *now=root;
for(i=0; i<len; i++){
int id=s[i]-'a';
while(now != root && now->next[id]==NULL)
now=now->fail;
if(now->next[id]==NULL) continue;
now=now->next[id];
Trie *tmp=now;
while(tmp!=root && tmp->cnt!=0){//找到某个关键字
ans+=tmp->cnt;
tmp->cnt=0;
tmp=tmp->fail;
}
}
}
void FreeTrie(Trie *tree)//释放空间
{
if(tree==NULL) return;
for(int i=0; i<26; i++){
if(tree->next[i]!=NULL) FreeTrie(tree->next[i]);
}
free(tree);
}
int main()
{
//freopen("in.txt","r",stdin);
int T;
char s[60];
scanf("%d", &T);
while(T--)
{
root=(Trie*)malloc(sizeof(Trie));
for(int i=0; i<26; i++) root->next[i]=NULL;
root->fail=NULL;
ans=0;
int n;
scanf("%d", &n);
while(n--){
scanf("%s", s);
CreateTrie(s);
}
CreateFail();
scanf("%s",str);
FindTrie(str);
printf("%d\n",ans);
FreeTrie(root);
}
return 0;
}