L 语言

https://loj.ac/problem/10053

题目描述

  给出一个字典和一个句子,求最多能理解到这句话的第几个位置(前缀)。

思路

  字典树,自然如同它的名字一样,可以用来处理字典的问题。首先显然我们可以建一棵字典树,接下来我们明确我们求的是能理解的前缀,而不是总长度,因此不是多字符串匹配,不用AC自动机。由于字典中的单词可能会有嵌套,我们考虑用f[i]表示我们是否可以匹配到这一位,所以我们可以从每一位可以匹配的地方出发,进行字符串匹配,再记录答案。而最大的i满足f[i]=1就是答案。

代码

#include <bits/stdc++.h>
using namespace std;
int ch[1000005][30],tot;
char s[30],ss[1000005];
bool ed[1000005],f[1000005];
void insert(char *s)
{
    int u=1,len=strlen(s);
    for(int i=0;i<len;i++)
    {
        int c=s[i]-'a';
        if(!ch[u][c])ch[u][c]=++tot;
        u=ch[u][c];
    }
    ed[u]=1;
}
int find(char *s)
{
    int u=1,len=strlen(s+1);
    int ans=0;
    memset(f,0,sizeof(f));
    f[0]=1;
    for(int i=0;i<=len;i++)
    {
        if(!f[i])continue ;
        else ans=i;
        u=1;
        for(int j=i+1;j<=len;j++)
        {
//            cout<<j<<' '<<s[j]<<endl;
            int c=s[j]-'a';
            if(!ch[u][c])break ;
            u=ch[u][c];
            if(ed[u])f[j]=1;
        }
    }
    return ans;
}
int main() 
{
    int n,m;
    scanf("%d%d",&n,&m);
    tot=1;
    for(int i=1;i<=n;i++)
    {
        scanf(" %s",s);
        insert(s);
    }
    for(int i=1;i<=m;i++)
    {
        scanf(" %s",ss+1);
        printf("%d\n",find(ss));
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/fangbozhen/p/11628563.html