题意:已知原串(长度为1~1000),它由多个单词组成,每个单词除了首尾字母,其余字母为乱序,且句子中无空格。给定n个互不相同的单词(1 <= n <= 10000),问是否能用这n个单词还原出这个句子。

eg:

  1. 3
  2. tihssnetnceemkaesprfecetsesne
  3. 5
  4. makes
  5. perfect
  6. sense
  7. sentence
  8. this
  9. hitehre
    应输出唯一解:this sentence makes perfect sense

分析:

1、将原串从头到尾遍历,分别以原串中的每个字母为基础,查找是否有以该字母为尾字母的单词,并判断该单词是否可以在原串的这个位置形成一种构造方法,dp[i]表示从开始到第 i 位有几种构成方法,因此,状态转移方程为dp[j] += dp[i - 1](若 i ~ j 位可以构成一个单词)

2、为了减小枚举量,通过num[]记录每个单词的字母个数,并用cnt[][]统计了元传中截止到每一位时各个字母的个数;

3、边dp边记录pre[i],以便最终输出符合要求的句子。

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<cstdlib>
  4. #include<cctype>
  5. #include<cmath>
  6. #include<iostream>
  7. #include<sstream>
  8. #include<iterator>
  9. #include<algorithm>
  10. #include<string>
  11. #include<vector>
  12. #include<set>
  13. #include<map>
  14. #include<stack>
  15. #include<deque>
  16. #include<queue>
  17. #include<list>
  18. typedef long long ll;
  19. typedef unsigned long long llu;
  20. const int INT_INF = 0x3f3f3f3f;
  21. const int INT_M_INF = 0x7f7f7f7f;
  22. const ll LL_INF = 0x3f3f3f3f3f3f3f3f;
  23. const ll LL_M_INF = 0x7f7f7f7f7f7f7f7f;
  24. const int dr[] = {, , -, };
  25. const int dc[] = {-, , , };
  26. const double pi = acos(-1.0);
  27. const double eps = 1e-;
  28. const int MAXN = + ;
  29. const int MAXT = + ;
  30. using namespace std;
  31. char s[MAXN];
  32. char x[MAXT][];
  33. int cnt[MAXN][];
  34. int dp[MAXN];
  35. int pre[MAXN];
  36. int markx[MAXN];
  37. int marky[MAXN];
  38. struct P{
  39. int len, id;
  40. char st;
  41. char num[];
  42. P(int l, int e, char h):len(l), id(e), st(h){
  43. memset(num, , sizeof num);
  44. for(int i = ; i < len; ++i){
  45. ++num[x[id][i] - 'a'];
  46. }
  47. }
  48. };
  49. vector<P> v[];
  50. bool judge(int a, int b, P &x){
  51. if(a == ){
  52. for(int i = ; i < ; ++i){
  53. if(x.num[i] != cnt[b][i]) return false;
  54. }
  55. return true;
  56. }
  57. else{
  58. for(int i = ; i < ; ++i){
  59. if(x.num[i] != cnt[b][i] - cnt[a - ][i]) return false;
  60. }
  61. return true;
  62. }
  63. }
  64. int main(){
  65. int T;
  66. scanf("%d", &T);
  67. while(T--){
  68. for(int i = ; i < ; ++i){
  69. v[i].clear();
  70. }
  71. memset(s, , sizeof s);
  72. memset(x, , sizeof x);
  73. memset(cnt, , sizeof cnt);
  74. memset(dp, , sizeof dp);
  75. memset(pre, -, sizeof pre);//不能初始化为0,这样会漏掉第一个字母是第一个单词这种情况
  76. memset(markx, , sizeof markx);
  77. memset(marky, , sizeof marky);
  78. scanf("%s", s);//原串
  79. int l = strlen(s);
  80. ++cnt[][s[] - 'a'];
  81. for(int i = ; i < l; ++i){//记录截止到原串中第i个字母时26个字母每个字母的个数
  82. for(int j = ; j < ; ++j){
  83. cnt[i][j] = cnt[i - ][j];
  84. }
  85. ++cnt[i][s[i] - 'a'];
  86. }
  87. int n;
  88. scanf("%d", &n);
  89. for(int i = ; i < n; ++i){
  90. scanf("%s", x[i]);
  91. int len = strlen(x[i]);
  92. char tmp = x[i][];
  93. v[x[i][len - ] - 'a'].push_back(P(len, i, tmp));//以单词的尾字母为下标,每个单词初始化长度,标号和首字母三个属性
  94. }
  95. for(int i = ; i < l; ++i){//分别以原串中的每个字母为基础,在vector中查找以该字母为尾字母的单词,并且该单词的首字母在原串中该字母的位置之前出现
  96. int t = v[s[i] - 'a'].size();
  97. for(int j = ; j < t; ++j){
  98. P& w = v[s[i] - 'a'][j];
  99. int tmp = i - w.len + ;//该字母的首字母在原串中所对应的下标
  100. if(tmp == && w.st == s[tmp] && judge(tmp, i, w)){//若查找到的这个单词是原串中的第一个单词且匹配
  101. ++dp[i];
  102. markx[i] = s[i] - 'a';
  103. marky[i] = j;
  104. }
  105. else if(tmp > && w.st == s[tmp] && judge(tmp, i, w) && dp[tmp - ]){//tmp>0,不是tmp!=0
  106. dp[i] += dp[tmp - ];
  107. pre[i] = tmp - ;
  108. markx[i] = s[i] - 'a';
  109. marky[i] = j;
  110. }
  111. }
  112. }
  113. if(!dp[l - ]){
  114. printf("impossible\n");
  115. }
  116. else if(dp[l - ] > ){
  117. printf("ambiguous\n");
  118. }
  119. else{
  120. stack <pair<int, int> > ss;
  121. while(!ss.empty()) ss.pop();
  122. for(int i = l - ; i != -; i = pre[i]){//##########
  123. ss.push(pair<int, int>(markx[i], marky[i]));
  124. }
  125. bool flag = true;
  126. while(!ss.empty()){
  127. pair<int, int> w = ss.top();
  128. ss.pop();
  129. if(flag) flag = false;
  130. else printf(" ");
  131. printf("%s", x[v[w.first][w.second].id]);
  132. }
  133. printf("\n");
  134. }
  135. }
  136. return ;
  137. }

HDU 2340 Obfuscation(dp)的更多相关文章

  1. HDU 4433 locker(DP)(2012 Asia Tianjin Regional Contest)

    Problem Description A password locker with N digits, each digit can be rotated to 0-9 circularly.You ...

  2. HDU 3008 Warcraft(DP)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3008 题目大意:人有100血和100魔法,每秒增加 t 魔法(不能超过100).n个技能,每个技能消耗 ...

  3. hdu 2059 龟兔赛跑(dp)

    龟兔赛跑 Problem Description 据说在很久很久以前,可怜的兔子经历了人生中最大的打击——赛跑输给乌龟后,心中郁闷,发誓要报仇雪恨,于是躲进了杭州下沙某农业园卧薪尝胆潜心修炼,终于练成 ...

  4. HDU 4832 Chess (DP)

    Chess Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submi ...

  5. HDU 4945 2048(dp)

    题意:给n(n<=100,000)个数,0<=a[i]<=2048 .一个好的集合要满足,集合内的数可以根据2048的合并规则合并成2048 .输出好的集合的个数%998244353 ...

  6. hdu 2571 命运(dp)

    Problem Description 穿过幽谷意味着离大魔王lemon已经无限接近了! 可谁能想到,yifenfei在斩杀了一些虾兵蟹将后,却再次面临命运大迷宫的考验,这是魔王lemon设下的又一个 ...

  7. HDU 6170----Two strings(DP)

    题目链接 Problem Description Giving two strings and you should judge if they are matched.The first strin ...

  8. HDU 2159 FATE (dp)

    FATE Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other) Total Submissi ...

  9. HDU 2059 龟兔赛跑 (dp)

    题目链接 Problem Description 据说在很久很久以前,可怜的兔子经历了人生中最大的打击--赛跑输给乌龟后,心中郁闷,发誓要报仇雪恨,于是躲进了杭州下沙某农业园卧薪尝胆潜心修炼,终于练成 ...

随机推荐

  1. BZOJ 1051: [HAOI2006]受欢迎的牛 缩点

    1051: [HAOI2006]受欢迎的牛 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/ ...

  2. HDU 5512 Meeting 博弈论

    Meeting Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5512 ...

  3. 获得临时文件目录(Temp文件夹)

    C:\Users\ADMINI~1\AppData\Local\Temp\   //GetTempPath获得临时文件目录(Temp文件夹)  function TempPath:String;var ...

  4. Android Bundle传递简单数据、对象数据

    Android开发过程中进程遇到组件之间.进程之间等数据的传递,数据传递有非常多种,当中使用Bundle传递非常方便. Bundle能够传递多种数据,是一种类似map的key-value数据结构 简单 ...

  5. web开发技术点解析

    一.控件篇 1.radio控件 在创建单选控件时,要做到多个radio有单选功能.必须把多个radio的name属性值设置为同样的,否则,多个radio之间是没有联系的. 二.样式篇 1.获取图片中的 ...

  6. Playing with ptrace, Part II

    Playing with ptrace, Part II Issue From Issue # December Dec , By Pradeep Padala inSysAdmin In Part ...

  7. 使用代码修改camera.cullingMask

    通过查找http://docs.unity3d.com/Documentation/ScriptReference/Camera-cullingMask.html只是能够指定某个层,但要指定多个层却不 ...

  8. mysql 日期函数格式

    mysql中的from_unixtime函数的format表达式字段描述: %M 月名字(January……December) %W 星期名字(Sunday……Saturday)  %D 有英语前缀的 ...

  9. 用CAS操作实现Go标准库中的Once

    Go标准库中提供了Sync.Once来实现"只执行一次"的功能.学习了一下源代码,里面用的是经典的双重检查的模式: // Once is an object that will p ...

  10. SpringMVC的简单示例

    首先导入所需的jar包,项目目录结构如下: 之后需要配置一下web.xml文件,内容如下: <?xml version="1.0" encoding="UTF-8& ...