zoukankan      html  css  js  c++  java
  • [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可以被理解的最长前缀的位置。

    输入输出样例

    输入样例#1:

    4 3
    is
    name
    what
    your
    whatisyourname
    whatisyouname
    whaisyourname

    输出样例#1:

    14 (整段文章’whatisyourname’都能被理解)
    6 (前缀’whatis’能够被理解)
    0 (没有任何前缀能够被理解)

    题解

    本来看错题意了,以为又是一道统计前缀的题目,打到一半一想.HNOI怎么可能考这种裸题,又转回去看题意,才发现是问可以匹配的完单词数

    那么其实我们可以用一种dp的思路(网上说的),其实我真没觉得是dp,就是隔一段打个标记,代表最远可以匹配到哪里,但是要注意一点:每次匹配单词都要从字典树的根节点开始匹配,如果匹配到了这个单词的末尾,就在当前位置打个标记,也就是说我们需要两重循环枚举,第一重循环枚举当前可以记录答案的位置,第二重循环枚举最远可以到达哪里

    时间复杂度分析:因为我们的第二重循环每次都是从i+1开始,文章长度最长为1M也就是1e6,所以其实应该是(O(m*10^6))

    Code

    Time (bzoj:892ms)

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #define Min(a,b) ((a)<(b)?(a):(b))
    #define Max(a,b) ((a)>(b)?(a):(b))
    #define in(i) (i=read())
    using namespace std;
    int read() {
        int ans=0,f=1; char i=getchar();
        while(i<'0' || i>'9') {if(i=='-') f=-1; i=getchar();}
        while(i>='0' && i<='9') {ans=(ans<<1)+(ans<<3)+i-'0'; i=getchar();}
        return ans*f;
    }
    int n,m,tot,ans;
    int trie[1000010][27],end[1000010],f[1000010];
    char s[1000010];
    inline void insert() {
        scanf("%s",s+1);
        int len=strlen(s+1),p=0;
        for(int i=1;i<=len;i++) {
            int c=s[i]-'a';
            if(!trie[p][c]) trie[p][c]=++tot;
            p=trie[p][c];
        }
        end[p]=1;
    }
    inline int search() {
        scanf("%s",s+1);
        int len=strlen(s+1),p=0,ans;
        memset(f,0,sizeof(f)); f[0]=1;
        for(int i=0;i<=len;i++) {
            if(!f[i]) continue;
            else ans=i;
            for(int j=i+1,p=0;j<=len;j++) {
                int c=s[j]-'a';
                p=trie[p][c];
                if(!p) break;
                if(end[p]) f[j]=1;
            }
        }
        return ans;
    }
    int main()
    {
        in(n); in(m);
        for(int i=1;i<=n;i++) insert();
        for(int i=1;i<=m;i++) printf("%d
    ",search());
        return 0;
    }
    

    博主蒟蒻,随意转载.但必须附上原文链接

    http://www.cnblogs.com/real-l/

  • 相关阅读:
    Python 学习笔记 11.模块(Module)
    Python 学习笔记 8.引用(Reference)
    Python 学习笔记 9.函数(Function)
    Python 学习笔记 6.List和Tuple
    Python 学习笔记 4.if 表达式
    Python 学习笔记 2.自省
    Python 学习笔记 3.简单类型
    Python 学习笔记 7.Dictionary
    Python 学习笔记 5.对象驻留
    Python 学习笔记 10.类(Class)
  • 原文地址:https://www.cnblogs.com/real-l/p/9376127.html
Copyright © 2011-2022 走看看