input

字符串s   1<=len(s)<=300000

n    1<=n<=4000

word1

word2

...

wordn

1<=len(wordi)<=100

output

由一个或多个word拼成s的种数%20071027.

做法1:dp:单词长度最多为100,d[i]表示到第i个字符结束的种数,则如果d[j]到d[i]这段字符能从trie中找到,d[i]+=d[j],i-100<j<=i

  1. //1225ms
  2. #include <cstdio>
  3. #include <queue>
  4. #include <cstring>
  5. #include <iostream>
  6. #include <cstdlib>
  7. #include <algorithm>
  8. #include <vector>
  9. #include <map>
  10. #include <set>
  11. #include <ctime>
  12. #include <cmath>
  13. #include <cctype>
  14. #define MAX 100000
  15. #define LL long long
  16. #define mod 20071027
  17. struct trie
  18. {
  19. int ch[*MAX][];
  20. bool val[*MAX];
  21. int sz;
  22. trie()
  23. {
  24. sz=;
  25. memset(ch[],,sizeof(ch[]));
  26. }
  27. int idx(char &c) { return c-'a';}
  28. char* insert(char*s)
  29. {
  30. int u=;
  31. for(;*s;s++)
  32. {
  33. int c=idx(*s);
  34. if(!ch[u][c])
  35. {
  36. memset(ch[sz],,sizeof(ch[sz]));
  37. val[sz]=;
  38. ch[u][c]=sz++;
  39. }
  40. u=ch[u][c];
  41. }
  42. val[u]=;
  43. return s;
  44. }
  45. int find(char*s,int n)
  46. {
  47. int u=;
  48. for(int i=;i<n;i++)
  49. {
  50. int c=idx(s[i]);
  51. if(!ch[u][c]) return ;
  52. u=ch[u][c];
  53. }
  54. return val[u];
  55. }
  56. };
  57. trie t;
  58. char s[*MAX+],word[];
  59. int n,maxl,d[*MAX+],cas=;
  60. int main()
  61. {
  62. //freopen("/home/user/桌面/in","r",stdin);
  63. while(scanf("%s",s)==)
  64. {
  65. memset(t.ch[],,sizeof(t.ch[]));
  66. t.sz=;
  67. scanf("%d",&n);
  68. maxl=;
  69. while(n--)
  70. {
  71. scanf("%s",word);
  72. int l=t.insert(word)-word;
  73. maxl=std::max(maxl,l);
  74. }
  75. n=strlen(s);
  76. memset(d,,sizeof(d));
  77. int u=,work=;
  78. for(int i=;i<maxl;i++)
  79. {
  80. int c=t.idx(s[i]);
  81. if(!t.ch[u][c]) break;
  82. u=t.ch[u][c];
  83. if(t.val[u])
  84. {
  85. work=;
  86. d[i]=;
  87. }
  88. }
  89. // for(int i=0;i<=n;i++) printf("%d ",d[i]);printf("\n");
  90. if(work)
  91. {
  92. for(int i=;i<n;i++)
  93. {
  94. for(int j=;j<=maxl;j++)
  95. {
  96. if(i-j>=&&t.find(s+i-j+,j)) d[i]=(d[i]+d[i-j])%mod;
  97. }
  98. }
  99. }
  100. // for(int i=0;i<=n;i++) printf("%d ",d[i]);printf("\n");
  101. printf("Case %d: %d\n",cas++,d[n-]);
  102. }
  103. //printf("time=%.3lf",(double)clock()/CLOCKS_PER_SEC);
  104. return ;
  105. }

dp

做法2:直接模拟:一开始只有一条路找,每个单词结束时分出一条路从头开始

  1. //79ms
  2. #include <cstdio>
  3. #include <queue>
  4. #include <cstring>
  5. #include <iostream>
  6. #include <cstdlib>
  7. #include <algorithm>
  8. #include <vector>
  9. #include <map>
  10. #include <set>
  11. #include <ctime>
  12. #include <cmath>
  13. #include <cctype>
  14. #define MAX 100000
  15. #define LL long long
  16. #define mod 20071027
  17. struct trie
  18. {
  19. int ch[*MAX][];
  20. bool val[*MAX];
  21. int sz;
  22. trie()
  23. {
  24. sz=;
  25. memset(ch[],,sizeof(ch[]));
  26. }
  27. int idx(char &c) { return c-'a';}
  28. void insert(char*s)
  29. {
  30. int u=;
  31. for(;*s;s++)
  32. {
  33. int c=idx(*s);
  34. if(!ch[u][c])
  35. {
  36. memset(ch[sz],,sizeof(ch[sz]));
  37. val[sz]=;
  38. ch[u][c]=sz++;
  39. }
  40. u=ch[u][c];
  41. }
  42. val[u]=;
  43. }
  44. };
  45. trie t;
  46. char s[*MAX+],word[];
  47. int n,cas=,head[][],count[][],num[];
  48. int main()
  49. {
  50. //freopen("/home/user/桌面/in","r",stdin);
  51. while(scanf("%s",s)==)
  52. {
  53. memset(t.ch[],,sizeof(t.ch[]));
  54. t.sz=;
  55. scanf("%d",&n);
  56. while(n--)
  57. {
  58. scanf("%s",word);
  59. t.insert(word);
  60. }
  61. int d=;
  62. num[d]=;
  63. head[d][]=;
  64. count[d][]=;
  65. for(char*p=s;*p;p++,d^=)
  66. {
  67. // printf("%d %d\n",count[d][0],d);
  68. int &idx=num[d^]=;
  69. int c=t.idx(*p);
  70. head[d^][]=;
  71. count[d^][]=;
  72. for(int i=;i<num[d];i++)
  73. {
  74. int &f=head[d][i];
  75. if(t.ch[f][c])//继续走到下一个字母
  76. {
  77. if(t.val[t.ch[f][c]])//走完一个单词,从头开始,总是head[d][0]
  78. {
  79. count[d^][]+=count[d][i];
  80. count[d^][]%=mod;
  81. }
  82. head[d^][idx]=t.ch[f][c];
  83. count[d^][idx++]=count[d][i];
  84. }
  85. }
  86. }
  87. // printf("%d %d\n",count[d][0],d);
  88. printf("Case %d: %d\n",cas++,count[d][]);
  89. }
  90. //printf("time=%.3lf",(double)clock()/CLOCKS_PER_SEC);
  91. return ;
  92. }

模拟

UVALive - 3942 Remember the Word的更多相关文章

  1. UVALive - 3942:Remember the Word

    发现字典里面的单词数目多且长度短,可以用字典树保存 f[i]表示s[i~L]的分割方式,则有f[i]=∑f[i+len(word[j])]   其中word[j]为s[i~L]的前缀 注意字典树又叫前 ...

  2. UVALive - 3942 Remember the Word[树状数组]

    UVALive - 3942 Remember the Word A potentiometer, or potmeter for short, is an electronic device wit ...

  3. UVALive - 3942 Remember the Word[Trie DP]

    UVALive - 3942 Remember the Word Neal is very curious about combinatorial problems, and now here com ...

  4. 【暑假】[实用数据结构]UVAlive 3942 Remember the Word

    UVAlive 3942 Remember the Word 题目: Remember the Word   Time Limit: 3000MS   Memory Limit: Unknown   ...

  5. UVALive 3942 Remember the Word 字典树+dp

    /** 题目:UVALive 3942 Remember the Word 链接:https://vjudge.net/problem/UVALive-3942 题意:给定一个字符串(长度最多3e5) ...

  6. UVALive 3942 Remember the Word

    题意:给出一个由S个不同单词组成的字典和一个长字符串.把这个字符串分解成若干个单词的连接(单词可以重复 使用),有多少种方法? Sample Input abcd 4 a b cd ab Sample ...

  7. Remember the Word UVALive - 3942(dp+trie)

    题意: 给S个不同的单词和一个长字符串 问将其分解为若干个单词有多少种方法(单词可重复使用) 解析: dp[i]表示在这个字符串中以某个位置i为起点的 的一段子字符串 则这个子字符串若存在某个前缀恰好 ...

  8. UVALive 3942 Remember The Word (Tire)

    状态是DAG,因此方案用dp统计,dp[i] = sum(dp[i+len(x)]),x是以i开头的前缀且是单词,关键在于快速判断一个前缀是不是单词,可用Trie. 每一次转移的复杂度是O(maxle ...

  9. UVALive - 3942 Remember the Word (Trie + DP)

    题意: 给定一篇长度为L的小写字母文章, 然后给定n个字母, 问有多少种方法用这些字母组成文章. 思路: 用dp[i]来表达[i , L]的方法数, 那么dp[i] 就可以从dp[len(x) + i ...

随机推荐

  1. jQuery Post 提交内容中有标签报错

    Post编辑一点内容要传后台数据库: var html = editor2.html() console.log(encodeURIComponent(html)); //console.log(&q ...

  2. 14.hibernate的反向生成实现全套增删改查

    图片顺序就是步骤顺序 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18.

  3. HDU 4520 小Q系列故事――最佳裁判(STL)

    小Q系列故事——最佳裁判 Problem Description 过去的2012年对小Q来说是很悲催的一年,失恋了12次,每次都要郁闷1个来月. 好在小Q是个体育迷,在最痛苦的时候,他常常用观看各种体 ...

  4. UNIX基础--权限

    权限 Permissions FreeBSD使用传统的UNIX®系统的基本权限.在UNIX®系统中,基本权限分配了三种访问类型:读.写.执行.权限可以用字母r.w.x表示:也可以用二进制数表示,按rw ...

  5. amazeui 后台模板

    <!doctype html> <html class="no-js"> <head> <meta charset="utf-8 ...

  6. python学习入门第一天总结

    虽然之前自己也看过许多关于python的视频,但一直没有动力与勇气,所以未能坚持且也没有学得这么深刻,这次希望通过python自动化培训,能够彻底改变自己,通过第一天的python学习,自己学到了许多 ...

  7. C++中构造函数或析构函数定义为private

    转自:http://www.blogjava.net/fhtdy2004/archive/2009/05/30/278971.html 很多情况下要求当前的程序中只有一个object.例如一个程序只有 ...

  8. matlab显示图像的横纵坐标

    imshow(I);title('公路');axis on;  %如果不需要,on改为off

  9. 2.编写IoDemo.java的Java应用程序,程序完成的功能是:首先读取text.txt文件内容,再通过键盘输入文件的名称为iodemo.txt,把text.txt的内容存入iodemo.txt

    package zuoye; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; ...

  10. Windows下QT4.8.4编译环境的搭建(转载http://blog.csdn.net/bestgonghuibin/article/details/38933141)

    开始使用QT了,所以第一步就是把环境搭起来,这里小记一下,以免以后忘记. 1. 下载安装文件 要使用QT功能,那么必须要下载QT的源码,还必须要一个是用QT的编译环境,可以是VS2010,也可以是专用 ...