您的位置:首页 > 其它

HDU 3065 病毒侵袭持续中 | AC自动机

2017-12-05 20:32 399 查看

原题链接

//中文题好感动啊!!!

题解:

比较裸的AC自动机吧,对所有模式串建个AC自动机之后

用网站源码在上面跑匹配.

注意AC自动机建的时候字符集是26就好,遇到源码中别的字符直接回到Root

每个结尾节点记个CNT,我也不知道不记会不会跪

还有!注意这是个多组数据

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#define Z 27
#define M 2000010
using namespace std;
struct node
{
int ch[Z],id,fail,cnt;
void clear()
{
memset(ch,0,sizeof(ch));
cnt=id=fail=0;
}
}t[50010];
int n,cnt[1010],tot=1;
char s[1010][60],text[M];
void insert(int id)
{
int p=1,len=strlen(s[id]);
for (int i=0;i<len;i++)
{
if (t

.ch[s[id][i]-'A']==0) t[t[p].ch[s[id][i]-'A']=++tot].clear(); p=t[p].ch[s[id][i]-'A']; } t[p].id=id; t[p].cnt++; } void BuildFail() { queue <int> q; t[1].fail=1; for (int i=0;i<26;i++) if (t[1].ch[i]==0) t[1].ch[i]=1; else t[t[1].ch[i]].fail=1,q.push(t[1].ch[i]); while (!q.empty()) { int u=q.front(),v,w; for (int i=0;i<26;i++) { v=t[t[u].fail].ch[i],w=t[u].ch[i]; if (w) t[w].fail=v,q.push(w); else t[u].ch[i]=v; } q.pop(); } } void query(char s[]) { int len=strlen(s),p=1; for (int i=0;i<len;i++) { if (s[i]>'Z' || s[i]<'A') { p=1; continue; } p=t[p].ch[s[i]-'A']; if (t[p].id!=0) cnt[t[p].id]+=t[p].cnt; } } void init() { memset(cnt,0,sizeof(cnt)); t[1].clear(); tot=1; } int main() { while (scanf("%d",&n)!=EOF) { init(); for (int i=1;i<=n;i++) scanf("%s",s[i]),insert(i); BuildFail(); getchar(); gets(text); query(text); for (int i=1;i<=n;i++) if (cnt[i]>0) printf("%s: %d\n",s[i],cnt[i]); } return 0; }

[p] 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: