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\n",ans);
64 }

祝AC哟!

 

posted @ 2017-02-22 18:13  F.W.Nietzsche  阅读(155)  评论(1编辑  收藏  举报