BZOJ1212 [HNOI2004] L语言
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1212
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可以被理解的最长前缀的位置。
Trie入门(其实很久之前就看了Trie只是一直没写)
写此题时遭遇玄学,迷之TLE,改了改把strlen函数从for里面移到外面就AC了?
2016.2.26 update:CZL说strlen函数的复杂度是O(n)的……
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 #define rep(i,l,r) for(int i=l; i<=r; i++) 6 #define clr(x,y) memset(x,y,sizeof(x)) 7 #define travel(x) for(Edge *p=last[x]; p; p=p->pre) 8 using namespace std; 9 struct Node{ 10 bool isleaf; 11 Node *ch[26]; 12 Node() : isleaf(0){ 13 clr(ch,0); 14 } 15 }t[210],*pt = t,*root = pt++; 16 int n,m; 17 char c[1100010]; 18 bool f[1100010]; 19 int main(){ 20 scanf("%d%d",&n,&m); 21 while (n--){ 22 scanf("%s",c); Node *p = root; 23 int len = strlen(c); 24 rep(i,0,len-1){ 25 if (!p->ch[c[i] - 'a']) p->ch[c[i] - 'a'] = pt++; 26 p = p->ch[c[i] - 'a']; 27 } 28 p->isleaf = 1; 29 } 30 while (m--){ 31 scanf("%s",c+1); clr(f,0); f[0] = 1; 32 int len = strlen(c+1); 33 rep(i,0,len-1) if (f[i]){ 34 Node *p = root; 35 for(int j=i+1; p->ch[c[j] - 'a']; j++){ 36 p = p->ch[c[j] - 'a']; 37 if (p->isleaf) f[j] = 1; 38 } 39 } 40 for(int i=len; i>=0; i--) 41 if (f[i]){ 42 printf("%d\n",i); break; 43 } 44 } 45 return 0; 46 }