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

                        --byBZOJ

    http://www.lydsy.com/JudgeOnline/problem.php?id=1212



    算是AC-自动机?DP?

    好吧也许不算;

    她就是个Trie上的暴力么。。。

    对文章的每个前缀f[i](长度为i)

    f[i]合法,仅当存在:f[j](j<i)合法,且j+1到i为一个单词

    然后,就对于每个i,枚举j(i-j>10):使f[j]合法,且j+1到i能被一个单词匹配

    对了就是匹配,建个AC-自动机,因为连fail都不(能)用,所以也就是个trie树了,对j+1到i进行匹配就行了。

    代码如下:

     1 #include<cstdio>
     2 #include<cstring>
     3 using namespace std;
     4 int m,n;
     5 char s[21];
     6 char word[1050001];
     7 struct ss{
     8     int ch[27];
     9 }trie[1501];
    10 int tot,biggest,smallest;
    11 int is_end[1501],fail[1501];
    12 int f[1050001];
    13 int que[10000];
    14 void bfs_fail();
    15 void compare();
    16 int main()
    17 {
    18     int i,j,k,len;
    19     scanf("%d%d",&n,&m);
    20     for(i=1;i<=n;i++){
    21         getchar();
    22         scanf("%s",s);
    23         len=strlen(s)-1;k=0;
    24         if(len>biggest)biggest=len;
    25         if(len<smallest)smallest=len;
    26         for(j=0;j<=len;j++){
    27             if(!trie[k].ch[s[j]-'a'])
    28                 trie[k].ch[s[j]-'a']=++tot;
    29             k=trie[k].ch[s[j]-'a'];
    30         }
    31         is_end[k]=1;
    32     }
    33     for(i=1;i<=m;i++){
    34         getchar();
    35         scanf("%s",word);
    36         compare();
    37     }
    38     return 0;
    39 }
    40 void compare(){
    41     memset(f,0,sizeof(f));
    42     int i,j,tem1=0,tem2=0,ans=0,len=strlen(word)-1;
    43     f[0]=1;
    44     for(i=1;i<=len+1;i++){
    45         for(j=i-smallest+1;j>=0&&j>=i-biggest-1;j--)
    46             if(f[j]){
    47                 tem1=0;tem2=j;
    48                 while(tem2<=i-1){
    49                     if(trie[tem1].ch[word[tem2]-'a']){
    50                         tem1=trie[tem1].ch[word[tem2]-'a'];
    51                         tem2++;
    52                     }
    53                     else
    54                         break;
    55                 }
    56                 if(tem2==i&&is_end[tem1]){
    57                         f[i]=1;
    58                         ans=i;
    59                         break;
    60                 }
    61             }
    62     }
    63     printf("%d
    ",ans);
    64 }

    祝AC哟!

  • 相关阅读:
    UEditor 编辑模板
    Task ProgressBar模拟现实完成后显示TextBox
    Java Lambda map返回部分属性
    Socket编程
    字节流和字符流
    File类
    volatile的作用和原理
    Java四种引用类型
    ThreadLocal
    孤儿进程和僵尸进程
  • 原文地址:https://www.cnblogs.com/nietzsche-oier/p/6430351.html
Copyright © 2011-2022 走看看