给出k个keyword,和一个字符串S.(仅大写字母)
求各个keyword出现的次数.
每个keyword在不同的位置出现即视为不同(可能出现重叠).
Input
MULTI TEST CASE!!
第一行,一个整数k(1<=k<=1000)
以下k行,每行一个不同字符串表示keyword(|keyword|<=50)
最后一行一个字符串S(|S|<=10^6)
Output
按次序输出每个keyword匹配的次数,共k行
每行keyword 冒号 空格 出现的次数(0次也输出)
Sample Input
2
A
AB
BAAB
Sample Output
A: 2
AB: 1
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
#include<cctype>
#include<map>
using namespace std;
const int maxn=80000;
struct Node
{
int num;//序号
int id;//在静态链表中的位置
Node* next[27];
Node* fail;
};
Node temp[maxn];
int tp;
int occ[maxn];
int n;
Node* root;
char mat[1100][55];
int cont[1100];
void reset(Node* p)
{
p->num=0;p->id=tp-1;
for(int i=0;i<27;i++) p->next[i]=NULL;
p->fail=root;
if(p==root) p->fail=NULL;
}
void init()
{
memset(cont,0,sizeof(cont));
tp=0;
root=&temp[tp++];
reset(root);
}
void insert(char* word,int index)
{
Node* p=root;
for(int i=0;word[i];i++)
{
int x;
if(isupper(word[i])) x=word[i]-'A';
else x=26;
if(p->next[x]==NULL)
{
p->next[x]=&temp[tp++];
reset(p->next[x]);
}
p=p->next[x];
}
p->num=index;
}
Node* que[maxn*4];
int front,rear;
void DFA()
{
Node* p=root;
front=rear=0;
que[rear++]=p;
while(front<rear)
{
Node* t=que[front++];
for(int i=0;i<27;i++)
{
Node* cnt=t->next[i];
if(cnt!=NULL)
{
Node* fath=t->fail;
while(fath!=NULL&&fath->next[i]==NULL)
{
fath=fath->fail;
}
if(fath!=NULL)
{
cnt->fail=fath->next[i];
}
else
{
cnt->fail=p;
}
que[rear++]=cnt;
}
}
}
}
void find(char* str)
{
memset(occ,0,sizeof(occ));
Node* p=root;
Node* fath;
Node* cnt;
for(int i=0;str[i];i++)
{
int x;
if(isupper(str[i])) x=str[i]-'A';
else x=26;
cnt=p->next[x];
if(cnt!=NULL)
{
occ[cnt->id]++;
// for(fath=cnt;fath!=NULL;fath=fath->fail)
// {
// if(fath->num)
// {
// cont[fath->num]++;
// }
// }
p=cnt;
}
else
{
fath=p->fail;
while(fath!=NULL&&fath->next[x]==NULL)
{
fath=fath->fail;
}
if(fath!=NULL)
{
cnt=fath->next[x];
occ[cnt->id]++;
// for(fath=cnt;fath!=NULL;fath=fath->fail)
// {
// if(fath->num)
// {
// cont[fath->num]++;
// }
// }
p=cnt;
}
else
{
p=root;
}
}
}
/*
//按照bfs逆序 优化 for(int i=rear-1;i>=0;i--) { int index=que[i]->id; if(occ[index]) { cnt=&temp[index]; if(cnt->num) cont[cnt->num]+=occ[index]; } if(cnt!=NULL) fath=cnt->fail; else continue; if(fath!=NULL) occ[fath->id]+=occ[index]; } */
for(int i=0;i<maxn;i++)
{
if(occ[i])
{
cnt=&temp[i];
for(fath=cnt;fath!=NULL;fath=fath->fail)
{
if(fath->num)
{
cont[fath->num]+=occ[i];
}
}
}
}
//用map会超时
// map<Node* ,int >::iterator it;
// for(it=q.begin();it!=q.end();it++)
// {
// Node* cnt=it->first;
// int tmp=it->second;
// for(fath=cnt;fath!=NULL;fath=fath->fail)
// {
// if(fath->num)
// {
// cont[fath->num]+=tmp;
// }
// }
// }
}
char str[2000000];
int main()
{
while(scanf("%d",&n)==1)
{
init();
for(int i=1;i<=n;i++)
{
scanf("%s",mat[i]);
memcpy(str,mat[i],sizeof(mat[i]));
insert(str,i);
}
DFA();
scanf("%s",str);
find(str);
for(int i=1;i<=n;i++)
{
printf("%s: %d/n",mat[i],cont[i]);
}
}
}