zoukankan      html  css  js  c++  java
  • 【bzoj1212】【HNOI2004】L语言

    题目描述

    标点符号的出现晚于文字的出现,所以以前的语言都是没有标点的。现在你要处理的就是一段没有标点的文章。

    一段文章T是由若干小写字母构成。一个单词W也是由若干小写字母构成。一个字典D是若干个单词的集合。我们称一段文章T在某个字典D下是可以被理解的,是指如果文章T可以被分成若干部分,且每一个部分都是字典D中的单词。

    例如字典D中包括单词{‘is’, ‘name’, ‘what’, ‘your’},则文章‘whatisyourname’是在字典D下可以被理解的,因为它可以分成4个单词:‘what’, ‘is’, ‘your’, ‘name’,且每个单词都属于字典D,而文章‘whatisyouname’在字典D下不能被理解,但可以在字典D’=D+{‘you’}下被理解。这段文章的一个前缀‘whatis’,也可以在字典D下被理解,而且是在字典D下能够被理解的最长的前缀。

    给定一个字典D,你的程序需要判断若干段文章在字典D下是否能够被理解。并给出其在字典D下能够被理解的最长前缀的位置。


    输入

    输入文件第一行是两个正整数n和m,表示字典D中有n个单词,且有m段文章需要被处理。之后的n行每行描述一个单词,再之后的m行每行描述一段文章。

    其中1<=n, m<=20,每个单词长度不超过10,每段文章长度不超过1M。


    输出

    对于输入的每一段文章,你需要输出这段文章在字典D可以被理解的最长前缀的位置。


    样例输入

    4 3 
    is
    name
    what
    your
    whatisyourname
    whatisyouname
    whaisyourname


    样例输出

    14
    6
    0


    题解

    trie+dp。dp[ i ] 表示位置 i 之前的前缀能不能被理解,那么 dp[ i ] = 1的条件为 存在 j ≤ i && dp[ j ] =1 && s[ j ] 到 s [ i ] 能被理解。

    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    #define ll long long
    
    const int maxn=1000+50;
    
    int n,m,t[maxn][30],len,tot,root;
    char c[1000000+50];
    bool word[maxn],dp[1000000+50];
    
    void insert(){
        len=strlen(c+1);
        root=0;int id;
        for(int i=1;i<=len;i++){
            id=c[i]-'a';
            if(!t[root][id]) t[root][id]=++tot;
            root=t[root][id];
        }
        word[root]=true;
    }
    
    void find(){
        len=strlen(c+1);
        memset(dp,0,sizeof(dp));
        dp[0]=1;
        root=0;int id;
        for(int i=0;i<len;i++){
            if(dp[i]){
                int j=i+1;
                root=t[0][c[j]-'a'];
                while(root&&j<=len){
                    if(word[root]) dp[j]=1;
                    root=t[root][c[++j]-'a'];
                }
            }
        }
        for(int i=len;i>=1;i--){
            if(dp[i]){
                printf("%d
    ",i); return ;
            }
        }
        printf("0
    ");
    }
    
    template<typename T>void read(T& aa){
        char cc; ll ff;aa=0;cc=getchar();ff=1;
        while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
        if(cc=='-') ff=-1,cc=getchar();
        while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
        aa*=ff;
    }
    
    int main(){
        memset(word,false,sizeof(word));
        read(n),read(m);
        for(int i=1;i<=n;i++){
            cin>>c+1;
            insert();
        }
        while(m--){
            cin>>c+1;
            find();
        }
        return 0;
    }
  • 相关阅读:
    AVR开发 Arduino方法(六) 内存子系统
    AVR开发 Arduino方法(五) 模数转换子系统
    AVR开发 Arduino方法(四) 串行通信子系统
    AVR开发 Arduino方法(三) 定时/计数器子系统
    AVR开发 Arduino方法(二) 中断子系统
    2014.5.17—所谓生活,就是让自己变得更好
    2014.5.10—做事分清时间地点
    2014.5.7—社交网络用户心理分析
    2014.5.7—20岁这几年
    2014.5.5—反向绑定域名,无需工信部备案
  • 原文地址:https://www.cnblogs.com/rlddd/p/9781665.html
Copyright © 2011-2022 走看看