[HNOI2004]L语言

题目:BZOJ1212、洛谷P2292。

题目大意:给你n个单词和m篇文章,如果一篇文章的前k个字符能分成若干个单词,那么就认为这k个字符能被理解,求每篇文章最多能被理解几个字符。

解题思路:由于单词长度最大为10,我们建一棵Trie,用c[i]表示前i个字符能否被理解,枚举i,然后从i往后扩展即可。有点类似dp的思想,具体见代码注释。

找了半天的错发现c数组没清空也是没谁了╮(╯▽╰)╭

C++ Code:

#include<cstdio>
#include<cstring>
using namespace std;
int n,m,ans;
char s[1000005];
bool c[1000005];//c[i]表示文章0~i能否被理解
struct trie{
    bool exist;
    trie* nxt[26];
    trie():exist(false){
        for(int i=0;i<26;++i)nxt[i]=NULL;
    }
}*d;
int main(){
    d=new trie;
    scanf("%d%d",&n,&m);
    while(n--){//构造字典树
        scanf("%s",s);
        trie* p=d;
        for(int i=0;s[i];++i){
            int v=s[i]-'a';
            if(p->nxt[v]==NULL)p->nxt[v]=new trie;
            p=p->nxt[v];
        }
        p->exist=true;
    }
    while(m--){//枚举单词开始的节点
        scanf("%s",s);
        ans=0;
        memset(c,0,sizeof(c)); 
        for(int i=0;s[i];++i)
        if(i==0||c[i-1]){//当i为0或前面的文章能被理解时才能继续
            trie* p=d;
            for(int l=1;l<=10;++l){//枚举单词长度
                if(!s[i+l-1])break;//超过s直接跳出
                p=p->nxt[s[i+l-1]-'a'];
                if(p==NULL)break;//不存在这个前缀时直接退出
                if(p->exist){//成功理解
                    c[i+l-1]=true;
                    if(ans<i+l)ans=i+l;
                }
            }
        }
        printf("%d
",ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/Mrsrz/p/7372215.html