zoukankan      html  css  js  c++  java
  • [HNOI2004]L语言

    Description

    标点符号的出现晚于文字的出现,所以以前的语言都是没有标点 的。现在你要处理的就是一段没有标点的文章。 一段文章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下能够被理解的最长前缀的位置。

    Input

    输入文件第一行是两个正整数n和m,表示字典D中有n个单词,且有m段文章需要被处理。 之后的n行每行描述一个单词,再之后的m行每行描述一段文章。 其中1<=n, m<=20,每个单词长度不超过10,每段文章长度不超过1M。

    Output

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

    Sample Input

    4 3
    is
    name
    what
    your
    whatisyourname
    whatisyouname
    whaisyourname

    Sample Output

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

    我们将所有的单词翻转存入$Trie$中。

    定义$bool$状态$f[i]$,表示$ch[1..i]$能否$(1/0)$被理解(字符串下标从$1$开始)。对于每次循环到的$i$,我们可以从$i$向前找到是否有单词匹配,若匹配,我们将$f[i] |= f[i-len]$,$len$为单词长度。

    若$f[i]$为真,则可更新答案。

    (由于单词的总字符长度不大,完全没必要用$AC$自动机。)

    转载自http://www.cnblogs.com/NaVi-Awson/p/7689127.html

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 int ch[10001][27],val[10001],f[1000001],len,pos,n,m,ans;
     7 char s[1000001];
     8 void insert(int len)
     9 {int i;
    10   int x=0;
    11   for (i=len;i>=1;i--)
    12     {
    13       if (ch[x][s[i]-'a']==0) ch[x][s[i]-'a']=++pos;
    14       x=ch[x][s[i]-'a'];
    15     }
    16   val[x]=1;
    17 }
    18 bool query(int len)
    19 {int i;
    20   int x=0,flag=0;
    21   for (i=len;i>=1;i--)
    22     {if (ch[x][s[i]-'a']) x=ch[x][s[i]-'a'];
    23       else return flag;
    24       if (val[x]) flag|=f[i-1];
    25       if (flag) return 1;
    26     }
    27   return 0;
    28 }
    29 int main()
    30 {int i;
    31   cin>>n>>m;
    32   for (i=1;i<=n;i++)
    33     {
    34       scanf("%s",s+1);
    35       insert(strlen(s+1));
    36     }
    37   while (m--)
    38     {
    39       memset(f,0,sizeof(f));
    40       scanf("%s",s+1);
    41       len=strlen(s+1);
    42       f[0]=1;ans=0;
    43       for (i=1;i<=len;i++)
    44     {
    45       f[i]=query(i);
    46       if (f[i]) ans=i;
    47     }
    48       cout<<ans<<endl;
    49     }
    50 }
  • 相关阅读:
    Java暑期学习第二十天日报
    Java暑期学习第十六天日报
    Java暑期学习第十七天日报
    使用C#创建SQLServer的存储过程 附带图片
    ASP.NET树形
    什么时候使用webservice1
    ASPxGridView动态增加列
    winform中treeView使用通用类
    Winform使用C#实现Treeview节点"正在展开..."效果
    C#实现字符串加密解密类
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/7701759.html
Copyright © 2011-2022 走看看