【[HNOI2004]L语言】

\(Trie\)树+\(DP\)

我们只需要做一个存在性dp就好了

对于每一个字符串,我们设\(f[i]\)表示从\(1\)\(i\)位是否能被完全匹配

首先\(f[0]=1\),之后我们对于每一个\(f[i]=1\)我们都可以往下匹配

具体的匹配方法自然是丢到\(Trie\)树上去,从\(i\)这位开始,一旦遇到一个结束标记就将这个结束标记对应位置的\(f[x]=1\),之后就可以了

#include<cstdio>
#include<cstring>
#include<iostream>
#define re register
#define maxn 1000005
char S[maxn];
int son[505][27],flag[505];
char T[11];
int cnt;
bool f[maxn];
inline int read()
{
    char c=getchar();
    int x=0;
    while(c<'0'||c>'9') c=getchar();
    while(c>='0'&&c<='9')
      x=(x<<3)+(x<<1)+c-48,c=getchar();
    return x;
}
int n,m;
inline void ins()
{
    int len=strlen(T+1);
    int now=0;
    for(re int i=1;i<=len;i++)
    {
        if(!son[now][T[i]-'a']) son[now][T[i]-'a']=++cnt;
        now=son[now][T[i]-'a'];
    }
    flag[now]=1;
}
inline void check(int x,int len)
{
    int now=0;
    for(re int i=x;i<=len;i++)
    {
        if(!son[now][S[i]-'a']) return;
        now=son[now][S[i]-'a'];
        if(flag[now]) f[i]=1;
    }
}
int main()
{
    n=read();m=read();
    for(re int i=1;i<=n;i++)
    {
        scanf("%s",T+1);
        ins();
    }
    for(re int t=1;t<=m;t++)
    {
        scanf("%s",S+1);
        memset(f,0,sizeof(f));
        f[0]=1;
        int len=strlen(S+1);
        int ans=0;
        for(re int i=0;i<=len;i++)
        {
            if(!f[i]) continue;
            ans=i;
            check(i+1,len);
        }
        if(!ans) puts("-1");
        else printf("%d",ans),putchar(10);
    }
    return 0;
}
posted @ 2019-01-02 11:58  asuldb  阅读(151)  评论(0编辑  收藏  举报