[BZOJ1212][HNOI2004]L语言

BZOJ
Luogu

sol

\(f_i\)表示文章的前\(i\)个字符是否可以被理解。每次匹配要暴跳\(fail\)到根,转移就是\(f_i|=f_{i-len}\),其中\(len\)是某个可以匹配的模式串的串长。

code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N = 100005;
int n,m,ch[26][N],fail[N],dep[N],tot,len,f[N*10];
char s[N*10];
queue<int>Q;
void Insert()
{
    scanf("%s",s);len=strlen(s);
    int x=0;
    for (int i=0;i<len;i++)
    {
        if (!ch[s[i]-'a'][x]) ch[s[i]-'a'][x]=++tot;
        x=ch[s[i]-'a'][x];
    }
    dep[x]=len;
}
void Get_Fail()
{
    for (int i=0;i<26;i++) if (ch[i][0]) Q.push(ch[i][0]);
    while (!Q.empty())
    {
        int u=Q.front();Q.pop();
        for (int i=0;i<26;i++)
            if (ch[i][u]) fail[ch[i][u]]=ch[i][fail[u]],Q.push(ch[i][u]);
            else ch[i][u]=ch[i][fail[u]];
    }
}
void Query()
{
    scanf("%s",s+1);len=strlen(s+1);
    memset(f,0,sizeof(f));f[0]=1;
    for (int i=1,x=0;i<=len;i++)
    {
        x=ch[s[i]-'a'][x];
        for (int t=x;t;t=fail[t])
            f[i]|=f[i-dep[t]];
    }
    for (int i=len;i>=0;i--) if (f[i]) return (void)printf("%d\n",i);
}
int main()
{
    scanf("%d %d",&n,&m);
    for (int i=1;i<=n;i++) Insert();
    Get_Fail();
    for (int i=1;i<=m;i++) Query();
    return 0;
}
posted @ 2018-01-25 10:30  租酥雨  阅读(138)  评论(0编辑  收藏  举报