您的位置:首页 > 其它

HDU 3065 病毒侵袭持续中(AC自动机(每个模式串出现次数))

2017-08-26 17:55 507 查看
http://acm.hdu.edu.cn/showproblem.php?pid=3065

题意:
求每个模式串出现的次数。

思路:

不难,把模板修改一下即可。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
#include<stack>
#include<queue>
#include<cmath>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int maxn=10000+5;

int n;
int num;
char str[1005][55];
char s[2000005];
int ans[1005];

struct Trie
{
int son[30];
int cnt;
int id;
int fail;
}t[1000*50+5];

void init(int x)
{
t[x].cnt=t[x].fail=0;
memset(t[x].son,0,sizeof(t[x].son));
}

void trie(char *s, int id)
{
int n=strlen(s);
int x=0;
for(int i=0;i<n;i++)
{
int c=s[i]-'A'+1;
if(!t[x].son[c])
{
num++;
init(num);
t[x].son[c]=num;
}
x=t[x].son[c];
}
t[x].cnt++;
t[x].id=id;
}

void buildAC()
{
queue<int> Q;
for(int i=1;i<=26;i++)  if(t[0].son[i])  Q.push(t[0].son[i]);
while(!Q.empty())
{
int x=Q.front(); Q.pop();
int fail=t[x].fail;
for(int i=1;i<=26;i++)
{
int y=t[x].son[i];
if(y)
{
t[y].fail=t[fail].son[i];
Q.push(y);
}
else t[x].son[i]=t[fail].son[i];
}
}
}

void query(char *s)
{
int n=strlen(s);
int x=0;
for(int i=0;i<n;i++)
{
if(!(s[i]>='A' && s[i]<='Z'))  {x=0;continue;}
int c=s[i]-'A'+1;
while(x && !t[x].son[c])  x=t[x].fail;
x=t[x].son[c];
int tmp=x;
while(tmp)  //回到0就不需要再计数了
{
if(t[tmp].cnt!=0) ans[t[tmp].id]++;
tmp=t[tmp].fail;
}
}
}

int main()
{
//freopen("in.txt","r",stdin);
while(~scanf("%d",&n))
{
num=0;
init(0);
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
ans[i]=0;
scanf("%s",str[i]);
trie(str[i],i);
}
buildAC();
scanf("%s",s);
query(s);
for(int i=1;i<=n;i++)
{
if(ans[i]) printf("%s: %d\n",str[i],ans[i]);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: