BZOJ1212: [HNOI2004]L语言 AC自动机

来源:互联网 发布:ubuntu切换root用户 编辑:程序博客网 时间:2024/05/29 06:39

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1212

把给定的单词建成一个AC自动机,然后把给的文章在上面跑即可。

f[i]表示能不能匹配到第i个字符,当第i个字符在AC自动机上走到了x节点,如果x是一个danger节点那么就一直跳x的fail指针,如果路径上有danger节点,f[i]|=f[i-w[x]] (其中w[x]表示:如果x为终止节点那么这个字符串的长度是多少)

#include<cmath>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<queue>using namespace std;const int M=1000005;const int N=1005;int n,m,f[M],e[N][30],fail[N],cnt=1,w[N];char s[M],ch[30];bool danger[N];void insert(){scanf("%s",ch+1);int x=1;for(int i=1;ch[i];i++){int o=ch[i]-'a'+1;if(!e[x][o]) e[x][o]=++cnt;x=e[x][o];}w[x]=strlen(ch+1);danger[x]=true;}queue<int>Q;void build(){for(int i=1;i<=26;i++) e[0][i]=1;fail[1]=0;Q.push(1);while(!Q.empty()){int x=Q.front();Q.pop();for(int i=1;i<=26;i++){int v=e[x][i];if(v) fail[v]=e[fail[x]][i],Q.push(v);else e[x][i]=e[fail[x]][i];}danger[x]|=danger[fail[x]];}}void match(){int x=1;for(int i=1;s[i];i++){int o=s[i]-'a'+1;x=e[x][o];if(danger[x]){int y=x;while(y){if(w[y]) f[i]|=f[i-w[y]];y=fail[y];}}}}int main(){scanf("%d%d",&n,&m);for(int i=1;i<=n;i++) insert();build();while(m--){scanf("%s",s+1);int len=strlen(s+1);memset(f,0,sizeof(f));f[0]=1;match();for(int i=len;i>=0;i--)if(f[i]) {printf("%d\n",i);break;}}}


0 0
原创粉丝点击