题意: 一个大的字符串中找出一些小的字符串是否存在其中(其中小的字符串都是大写字母,大字符串里的字符则所有字符都可能)
注意:多数据处理,注意初始化
#include<iostream>
#include<queue>
using namespace std;
const int kind=26;
struct my
{
int index;
struct my *fail,*next[kind];
my()
{
index=0;
fail=NULL;
memset(next,NULL,sizeof(next));
}
};
char go[1111][55];
char s[2222222];
void insert(my *root,char *s,int n)
{
my *cur=root;
int i=0;
while (s[i])
{
int index=s[i++]-'A';
if (!cur->next[index]) cur->next[index] = new my;
cur=cur->next[index];
}
cur->index = n;
}
void build_fail(my *root)
{
queue<my*> q;
q.push(root);
while (!q.empty())
{
my *cur=q.front();
q.pop();
for (int i=0;i<kind;i++) if (cur->next[i])
{
q.push(cur->next[i]);
if (cur==root)
{
cur->next[i]->fail = root;
continue;
}
my *temp=cur->fail;
while (temp)
{
if (temp->next[i])
{
cur->next[i]->fail = temp->next[i];
break;
}
temp=temp->fail;
}
if (!temp) cur->next[i]->fail = root;
}
}
}
int ans[1111];
void query(my *root)
{
int i=0;
my *cur=root;
while (s[i]) if (s[i]>='A' && s[i]<='Z')
{
int index=s[i++]-'A';
//cout<<i<<' '<<s[i-1]<<' '<<root->next[index]<<endl;
while (!cur->next[index] && cur!=root) cur = cur->fail;
if (cur->next[index]) cur=cur->next[index];
else cur = root;
my *temp=cur;
while (temp!=root)
{
if (temp->index) ans[temp->index]++;
temp = temp->fail;
}
}
else cur=root,i++;
}
int main()
{
freopen("in","r",stdin);
int n;
while (cin>>n)
{
my *root=new my;
for (int i=1;i<=n;i++) scanf("%s",go[i]),insert(root,go[i],i);
build_fail(root);
scanf("%s",s);
query(root);
for (int i=1;i<=n;i++) if (ans[i])
{
printf("%s: %d\n",go[i],ans[i]);
}memset(ans,0,sizeof(ans));
}
}