标签:else mat strlen text ide dong 模板 register return
时间有限,只过了板子和少数题目。。在应该搞DP的时候搞这个。。
关于AC自动机的介绍,LuoGu日报讲的挺好的,可以比较好的入门。
一、模板
#include<bits/stdc++.h> #define RG register #define IL inline #define LL long long using namespace std; IL int gi () { RG int x=0,w=0; char ch=0; while (ch<‘0‘||ch>‘9‘) {if (ch==‘-‘) w=1;ch=getchar();} while (ch>=‘0‘&&ch<=‘9‘) x=(x<<3)+(x<<1)+(ch^48),ch=getchar(); return w?-x:x; } const int N=1e6+10; int n,ans,tot[210]; char str[N],ss[210][110]; namespace AC_Automaton { queue <int> q; int num,cnt[N],f[N],tr[N][27]; IL void New () { num=0; while (!q.empty()) q.pop(); memset(f,0,sizeof(f)); memset(tr,0,sizeof(tr)); memset(cnt,0,sizeof(cnt)); } IL void Insert (char s[],int id) { RG int i,p=0,now,len=strlen(s); for (i=0;i<len;++i) { now=s[i]-‘a‘+1; if (!tr[p][now]) tr[p][now]=++num; p=tr[p][now]; } cnt[p]=id; } IL void Get_Fail () { RG int i,p; for (i=1;i<=26;++i) if (tr[0][i]) q.push(tr[0][i]); while (!q.empty()) { p=q.front(),q.pop(); for (i=1;i<=26;++i) if (tr[p][i]) f[tr[p][i]]=tr[f[p]][i],q.push(tr[p][i]); else tr[p][i]=tr[f[p]][i]; // *类似并查集路径压缩* // *所以可以一步到位* } } IL void Search (char s[]) { int i,j,p=0,len=strlen(s); for (i=0;i<len;++i) { p=tr[p][s[i]-‘a‘+1]; for (j=p;j;j=f[j]) if (cnt[j]) ++tot[cnt[j]]; } } } using namespace AC_Automaton; int main () { RG int i; while ((n=gi())!=0) { ans=0,New(); memset(tot,0,sizeof(tot)); for (i=1;i<=n;++i) scanf("%s",ss[i]),Insert(ss[i],i); scanf("%s",str); Get_Fail(); Search(str); for (i=1;i<=n;++i) if (tot[i]>ans) ans=tot[i]; printf("%d\n",ans); for (i=1;i<=n;++i) if (tot[i]==ans) printf("%s\n",ss[i]); } return 0; }
我的不知道为什么跑的贼慢。。。
硬是不会rand一个puts??对于一个刚入门AC自动机的人来说,这个题还是有点意思的。。
先建一颗AC自动机,每个串结尾打上标记。
我们这样考虑一下:
如果我们拿最后那个合法的序列去AC自动机上匹配,那么我们会发现它恰好能避开所有打了标记的节点,通过fail指针在AC自动机上打转。
那么我们是不是只要在这个AC自动机上找到一个不含任何病毒节点的环就好了??
怎么找??
标签:else mat strlen text ide dong 模板 register return
原文地址:https://www.cnblogs.com/Bhllx/p/10329982.html