1. 程式人生 > >【[HNOI2004]L語言】

【[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;
}