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

eg:

3
tihssnetnceemkaesprfecetsesne
5
makes
perfect
sense
sentence
this
hitehre应输出唯一解:this sentence makes perfect sense

分析:

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

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

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

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<cmath>
#include<iostream>
#include<sstream>
#include<iterator>
#include<algorithm>
#include<string>
#include<vector>
#include<set>
#include<map>
#include<stack>
#include<deque>
#include<queue>
#include<list>
typedef long long ll;
typedef unsigned long long llu;
const int INT_INF = 0x3f3f3f3f;
const int INT_M_INF = 0x7f7f7f7f;
const ll LL_INF = 0x3f3f3f3f3f3f3f3f;
const ll LL_M_INF = 0x7f7f7f7f7f7f7f7f;
const int dr[] = {0, 0, -1, 1};
const int dc[] = {-1, 1, 0, 0};
const double pi = acos(-1.0);
const double eps = 1e-8;
const int MAXN = 1000 + 10;
const int MAXT = 10000 + 10;
using namespace std;
char s[MAXN];
char x[MAXT][110];
int cnt[MAXN][30];
int dp[MAXN];
int pre[MAXN];
int markx[MAXN];
int marky[MAXN];
struct P{int len, id;char st;char num[30];P(int l, int e, char h):len(l), id(e), st(h){memset(num, 0, sizeof num);for(int i = 0; i < len; ++i){++num[x[id][i] - 'a'];}}
};
vector<P> v[30];
bool judge(int a, int b, P &x){if(a == 0){for(int i = 0; i < 26; ++i){if(x.num[i] != cnt[b][i]) return false;}return true;}else{for(int i = 0; i < 26; ++i){if(x.num[i] != cnt[b][i] - cnt[a - 1][i]) return false;}return true;}
}
int main(){int T;scanf("%d", &T);while(T--){for(int i = 0; i < 30; ++i){v[i].clear();}memset(s, 0, sizeof s);memset(x, 0, sizeof x);memset(cnt, 0, sizeof cnt);memset(dp, 0, sizeof dp);memset(pre, -1, sizeof pre);//不能初始化为0,这样会漏掉第一个字母是第一个单词这种情况memset(markx, 0, sizeof markx);memset(marky, 0, sizeof marky);scanf("%s", s);//原串int l = strlen(s);++cnt[0][s[0] - 'a'];for(int i = 1; i < l; ++i){//记录截止到原串中第i个字母时26个字母每个字母的个数for(int j = 0; j < 26; ++j){cnt[i][j] = cnt[i - 1][j];}++cnt[i][s[i] - 'a'];}int n;scanf("%d", &n);for(int i = 0; i < n; ++i){scanf("%s", x[i]);int len = strlen(x[i]);char tmp = x[i][0];v[x[i][len - 1] - 'a'].push_back(P(len, i, tmp));//以单词的尾字母为下标,每个单词初始化长度,标号和首字母三个属性
        }for(int i = 0; i < l; ++i){//分别以原串中的每个字母为基础,在vector中查找以该字母为尾字母的单词,并且该单词的首字母在原串中该字母的位置之前出现int t = v[s[i] - 'a'].size();for(int j = 0; j < t; ++j){P& w = v[s[i] - 'a'][j];int tmp = i - w.len + 1;//该字母的首字母在原串中所对应的下标if(tmp == 0 && w.st == s[tmp] && judge(tmp, i, w)){//若查找到的这个单词是原串中的第一个单词且匹配++dp[i];markx[i] = s[i] - 'a';marky[i] = j;}else if(tmp > 0 && w.st == s[tmp] && judge(tmp, i, w) && dp[tmp - 1]){//tmp>0,不是tmp!=0dp[i] += dp[tmp - 1];pre[i] = tmp - 1;markx[i] = s[i] - 'a';marky[i] = j;}}}if(!dp[l - 1]){printf("impossible\n");}else if(dp[l - 1] > 1){printf("ambiguous\n");}else{stack <pair<int, int> > ss;while(!ss.empty()) ss.pop();for(int i = l - 1; i != -1; i = pre[i]){//##########ss.push(pair<int, int>(markx[i], marky[i]));}bool flag = true;while(!ss.empty()){pair<int, int> w = ss.top();ss.pop();if(flag) flag = false;else printf(" ");printf("%s", x[v[w.first][w.second].id]);}printf("\n");}}return 0;
}

转载于:https://www.cnblogs.com/tyty-Somnuspoppy/p/6030928.html

HDU 2340 Obfuscation(dp)相关推荐

  1. HDU 2340 - Obfuscation(dp)

    题意:一个句子中有多个单词,但是目前的单词,除了首末两位,中间的单词字母顺序均被打乱,并且打乱后把单词间的空格删掉变成一个新句子.现在给定这个新句子(长度为1~1000),给定n个单词(1 <= ...

  2. hdu 4433 locker(DP)

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=4433 题目大意:就是给你一个序列,相当于一个可以转的那种密码锁的初始状态,0往下转是9,9往上转是0,现在 ...

  3. HDU 2059 龟兔赛跑(DP)

    题意   中文 简单的多阶段决策DP   令p[0]=0   p[n]=l   d[i]表示乌龟从起点到第i个加油站所需的最小时间   那么有d[i]=min(d[i],d[j]+t(j,i))   ...

  4. hdu 2154 跳舞毯 (DP)

    点击打开链接 dp[i]=dp[i-1]+2*dp[i-2] #include"stdio.h" int main() {__int64 dp[1005];int i;int n; ...

  5. HDU 1248 冰封王座(dp)

    Problem Description 不死巫妖王拉工资,死亡骑士得到N美元的钞票(记,只有一个纸币),战斗中频繁的死掉,他决定给自己买一些道具,于是他来到了地精商店前. 死亡骑士:"我要买 ...

  6. HDU 2859 Phalanx(DP)

    基础DP #include<iostream> #include<algorithm> #include<cstring> #include<string&g ...

  7. HDU6578 2019HDU多校训练赛第一场 1001 (dp)

    HDU6578 2019HDU多校训练赛第一场 1001 (dp) 传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6578 题意: 你有n个空需要去填,有 ...

  8. HDU-1284:钱币兑换问题 推理+动态规划(dp)

    文章目录 题目大意: 题目链接HDU 1284(点击可进入网页提交) 在一个国家仅有1分,2分,3分硬币,将钱N兑换成硬币有很多种兑法.请你编程序计算出共有多少种兑法. 输入: 每行只有一个正整数N, ...

  9. 求三角形最大面积(DP)

    求三角形最大面积(DP) 在OJ上奇迹般WA了:WA:70. Why? #include <iostream> #include <string.h> using namesp ...

最新文章

  1. sharding jdbc:分库、分表;读写分离;
  2. 没有流程的项目管理,都是无用功!
  3. 太强了!Kaggle竞赛宝典方案汇总
  4. 【安卓开发 】Android初级开发(零)各种布局
  5. oracle sqlplus执行脚本_连接Oracle出错:sqlplus quot;/as sysdbaquot;
  6. php.ini详细介绍与设置,配置
  7. Windows7下安装配置PHP开发环境
  8. C#中lock关键字的用法
  9. Vs2010中水晶报表引用及打包
  10. 用 Webgoat 撬动地球,看安全测试的引路石!
  11. 移植conda环境到另一台服务器上
  12. EasyCVR在调用云台控制接口时出现ptz crtl error,error code 12的原因分析
  13. 计算机结构体系:系统CPI计算例题(1.5)
  14. ValueError: Sample larger than population or is negative...
  15. android实现单词测试功能,android项目实战-背呗单词DEV07-单词测试实现(示例代码)...
  16. 荣之学:跨境电商和淘宝哪个好?
  17. 想开发微信小程序分销商城需要做好哪些地方?
  18. java汉字转换为拼音
  19. Anddroid IM来电铃声通过耳机播放
  20. google instant

热门文章

  1. 浙江省计算机专业专科院校排名,浙江省高职院校“五强”
  2. web 流程设计器探究
  3. pdf压缩的网站?pdf文件在线压缩?在线压缩pdf文件大小?pdf文档压缩,在线压缩pdf文件大小,压缩pdf大小的方法?
  4. 关于Gradle新版插件依赖方式
  5. 选择使用Linux的理由
  6. CVPR2020:Seeing Through Fog Without Seeing Fog
  7. 【教学类-16-01】20221121《数字卡片9*2》(中班)
  8. 计算机学习资料(全)——含视频资料
  9. 网页向女友告白和纪念日专用特效
  10. Java-编写一个类 Book,代表图书