题意:

演队在口试中非常不幸。在42道考题中,他恰好没有准备最后一道题,而刚好被问到的正是那道题。演队坐在教授面前,一句话也说不出来。但教授心情很好,给了演队最后一次通过考试的机会。他让这个可怜的学生说出考试要考的科目。不幸的是,演队想不起这个科目名字,尽管他记得科目里有诸如安全、程序、设备、可能还有信息学……

为了准备复试,演队决定记住这门课的名字。为了更好地记住那根长字符串,他决定把它分解成回文,并分别学习每个回文。当然,分解过程中的回文数必须尽可能少。

Input

输入一行字符串表示为这门课的名字。这是由小写英文字母组成的非空行。这一行的长度最多是4000个字符。

Output

  1. 第一行输出可以分解科目名称的最小的回文字符串数目。在第二行输出回文所有的回文字符串,由空格分隔。如果有几个答案是可能的,输出其中任何一个。

Input

pasoib

Output

6
p a s o i b

Input

zzzqxx

Output

3
zzz q xx

Input

wasitacatisaw

Output

1
wasitacatisaw

题解:

可以对每一个区间[l,r]用哈希赋一个唯一的值,对区间[l,r]正序哈希一个值,逆序哈希一个值。那么如果区间[l,r]是回文串,那么这个区间的正序哈希值应该等于逆序哈希值

dp[i]=min(dp[j-1]+1,dp[i]),dp[i]代表从1-i区间的回文序列数量

这个状态转移方程就是当区间[j,i]是回文串的时候

如果不会哈希,也可以用一个二维数组来记录一下区间[l,r]是不是回文串,判断回文串就用while循环(这种方法见代码2)

代码1:

  1. 1 #include<stdio.h>
  2. 2 #include<string.h>
  3. 3 #include<iostream>
  4. 4 #include<algorithm>
  5. 5 #include<queue>
  6. 6 #include<vector>
  7. 7 #include<map>
  8. 8 #define mem(a,x) memset(a,x,sizeof(a))
  9. 9 using namespace std;
  10. 10 const int INF=0x3f3f3f3f;
  11. 11 const int maxn=4005;
  12. 12 const int mod=1000000009;
  13. 13 const int base=13333;
  14. 14 typedef long long ll;
  15. 15 ll dp[maxn];//从1--i中回文串的最少个数
  16. 16 ll h1[maxn],h2[maxn],p[maxn],n;
  17. 17 ll pre[maxn];
  18. 18 char s[maxn];
  19. 19 string str[maxn];
  20. 20 //找出来[l,r]这个区间正序的哈希值
  21. 21 ll get1(ll l,ll r)
  22. 22 {
  23. 23 return h1[r]-h1[l-1]*p[r-l+1];
  24. 24 }
  25. 25 //找出来[l,r]这个区间倒序的哈希值
  26. 26 ll get2(ll l,ll r)
  27. 27 {
  28. 28 return h2[r]-h2[l-1]*p[r-l+1];
  29. 29 }
  30. 30 //如果区间[l,r]的正序逆序哈希值一样,那么这个区间就是回文串
  31. 31 bool check(ll i,ll j)
  32. 32 {
  33. 33 if(get1(i,j)==get2(n-j+1,n-i+1))
  34. 34 return true;
  35. 35 return false;
  36. 36 }
  37. 37 int main()
  38. 38 {
  39. 39 ios::sync_with_stdio(false);
  40. 40 cin.tie(0);
  41. 41 memset(dp,INF,sizeof dp);
  42. 42 dp[0]=0;
  43. 43 cin>>(s+1);
  44. 44 n=strlen(s+1);
  45. 45 p[0]=1;
  46. 46 for(ll i=1; i<=n; i++)
  47. 47 {
  48. 48 h1[i]=h1[i-1]*base-s[i]-'a'+1;
  49. 49 h2[i]=h2[i-1]*base-s[n+1-i]-'a'+1;
  50. 50 p[i]=p[i-1]*base;
  51. 51 }
  52. 52 for(ll i=1; i<=n; i++)
  53. 53 {
  54. 54 for(ll j=1; j<=i; j++)
  55. 55 {
  56. 56 if(check(j,i))
  57. 57 {
  58. 58 if(dp[i]>(dp[j-1]+1))
  59. 59 {
  60. 60 pre[i]=j; //记录路径
  61. 61 dp[i]=dp[j-1]+1;
  62. 62 }
  63. 63 }
  64. 64 }
  65. 65 }
  66. 66 cout<<dp[n]<<endl;
  67. 67 int id=0;
  68. 68 int now=n;
  69. 69 while(now)
  70. 70 {
  71. 71 for(int i=pre[now]; i<=now; i++)
  72. 72 str[id]+=s[i]; //str串记录回文串
  73. 73 now=pre[now]-1;
  74. 74 id++;
  75. 75 }
  76. 76 for(int i=id-1; i>=0; i--)
  77. 77 {
  78. 78 if(i!=0)
  79. 79 cout<<str[i]<<' ';
  80. 80 else
  81. 81 cout<<str[i]<<endl;
  82. 82 }
  83. 83 }

代码2:(参考:https://blog.csdn.net/zmx354/article/details/20078995)

  1. 1 #include <iostream>
  2. 2
  3. 3 #include <algorithm>
  4. 4
  5. 5 #include <cstdlib>
  6. 6
  7. 7 #include <cstdio>
  8. 8
  9. 9 #include <cstring>
  10. 10
  11. 11 #include <queue>
  12. 12
  13. 13 #include <cmath>
  14. 14
  15. 15 #include <stack>
  16. 16
  17. 17
  18. 18
  19. 19 #pragma comment(linker, "/STACK:1024000000");
  20. 20
  21. 21 #define LL long long int
  22. 22
  23. 23 #define ULL unsigned long long int
  24. 24
  25. 25 #define _LL __int64
  26. 26
  27. 27 #define INF 0x3f3f3f3f
  28. 28
  29. 29 #define Mod 1000000009
  30. 30
  31. 31
  32. 32
  33. 33 using namespace std;
  34. 34
  35. 35
  36. 36
  37. 37 char s[4010];
  38. 38
  39. 39
  40. 40
  41. 41 bool dp[4001][4001];
  42. 42
  43. 43
  44. 44
  45. 45 int ans[4010];
  46. 46
  47. 47
  48. 48
  49. 49 int di[4010];
  50. 50
  51. 51
  52. 52
  53. 53 void Output(int l)
  54. 54
  55. 55 {
  56. 56
  57. 57 if(l == 0)
  58. 58
  59. 59 return ;
  60. 60
  61. 61
  62. 62
  63. 63 Output(di[l]);
  64. 64
  65. 65
  66. 66
  67. 67 if(di[l] != 0)
  68. 68
  69. 69 printf(" ");
  70. 70
  71. 71
  72. 72
  73. 73 for(int i = di[l]+1;i <= l; ++i)
  74. 74
  75. 75 {
  76. 76
  77. 77 printf("%c",s[i]);
  78. 78
  79. 79 }
  80. 80
  81. 81 }
  82. 82
  83. 83
  84. 84
  85. 85 int main()
  86. 86
  87. 87 {
  88. 88
  89. 89 int l,i,j,h,e;
  90. 90
  91. 91
  92. 92
  93. 93 scanf("%s",s+1);
  94. 94
  95. 95
  96. 96
  97. 97 l = strlen(s+1);
  98. 98
  99. 99
  100. 100
  101. 101 memset(dp,false,sizeof(dp));
  102. 102
  103. 103
  104. 104
  105. 105 for(i = 1;i <= l; ++i)
  106. 106
  107. 107 {
  108. 108
  109. 109 dp[i][i] = true;
  110. 110
  111. 111 h = i-1;
  112. 112
  113. 113 e = i+1;
  114. 114
  115. 115
  116. 116
  117. 117 while(1 <= h && e <= l && s[h] == s[e])
  118. 118
  119. 119 {
  120. 120
  121. 121 dp[h][e] = true;
  122. 122
  123. 123 h--,e++;
  124. 124
  125. 125 }
  126. 126
  127. 127
  128. 128
  129. 129 h = i,e = i+1;
  130. 130
  131. 131
  132. 132
  133. 133 while(1 <= h && e <= l && s[h] == s[e])
  134. 134
  135. 135 {
  136. 136
  137. 137 dp[h][e] = true;
  138. 138
  139. 139 h--,e++;
  140. 140
  141. 141 }
  142. 142
  143. 143 }
  144. 144
  145. 145
  146. 146
  147. 147 memset(ans,INF,sizeof(ans));
  148. 148
  149. 149
  150. 150
  151. 151 ans[0] = 0;
  152. 152
  153. 153
  154. 154
  155. 155 di[1] = 0;
  156. 156
  157. 157
  158. 158
  159. 159 for(i = 1;i <= l; ++i)
  160. 160
  161. 161 {
  162. 162
  163. 163 for(j = i;j >= 1; --j)
  164. 164
  165. 165 {
  166. 166
  167. 167 if(dp[j][i])
  168. 168
  169. 169 {
  170. 170
  171. 171 if(ans[i] > ans[j-1]+1)
  172. 172
  173. 173 {
  174. 174
  175. 175 ans[i] = ans[j-1]+1;
  176. 176
  177. 177 di[i] = j-1;
  178. 178
  179. 179 }
  180. 180
  181. 181 }
  182. 182
  183. 183 }
  184. 184
  185. 185 }
  186. 186
  187. 187
  188. 188
  189. 189 printf("%d\n",ans[l]);
  190. 190
  191. 191
  192. 192
  193. 193 Output(l);
  194. 194
  195. 195
  196. 196
  197. 197 puts("");
  198. 198
  199. 199
  200. 200
  201. 201 return 0;
  202. 202
  203. 203 }

URAL - 1635 哈希区间(或者不哈希)+dp的更多相关文章

  1. URAL 1635 Mnemonics and Palindromes

    URAL 1635 思路:区间dp+贪心,先n^2处理出每段区间是否是回文串,然后贪心地找每一段1到i的最少分割. 代码: #include<bits/stdc++.h> using na ...

  2. 回文串+回溯法 URAL 1635 Mnemonics and Palindromes

    题目传送门 /* 题意:给出一个长为n的仅由小写英文字母组成的字符串,求它的回文串划分的元素的最小个数,并按顺序输出此划分方案 回文串+回溯:dp[i] 表示前i+1个字符(从0开始)最少需要划分的数 ...

  3. Ural 1635 Mnemonics and Palindromes(DP)

    题目地址:space=1&num=1635">Ural 1635 又是输出路径的DP...连着做了好多个了. . 状态转移还是挺简单的.要先预处理出来全部的回文串,tag[i] ...

  4. Codeforces 811C Vladik and Memorable Trip (区间异或最大值) (线性DP)

    <题目链接> 题目大意: 给你n个数,现在让你选一些区间出来,对于每个区间中的每一种数,全部都只能出现在这个区间. 每个区间的价值为该区间不同的数的异或值之和,现在问你这n个数最大的价值是 ...

  5. Java集合(九)哈希冲突及解决哈希冲突的4种方式

    Java集合(九)哈希冲突及解决哈希冲突的4种方式 一.哈希冲突 (一).产生的原因 哈希是通过对数据进行再压缩,提高效率的一种解决方法.但由于通过哈希函数产生的哈希值是有限的,而数据可能比较多,导致 ...

  6. URAL 1635. Mnemonics and Palindromes(DP)

    题目链接 本来用区间DP,3次方的复杂度,T了,看了看题解,降维,直接二次方的复杂度可以解.然后折腾一下输出路径..终于过了. #include <cstring> #include &l ...

  7. Ural 1183 Brackets Sequence(区间DP+记忆化搜索)

    题目地址:Ural 1183 最终把这题给A了.. .拖拉了好长时间,.. 自己想还是想不出来,正好紫书上有这题. d[i][j]为输入序列从下标i到下标j最少须要加多少括号才干成为合法序列.0< ...

  8. Memcached 笔记与总结(5)Memcached 的普通哈希分布和一致性哈希分布

    普通 Hash 分布算法的 PHP 实现 首先假设有 2 台服务器:127.0.0.1:11211 和 192.168.186.129:11211 当存储的 key 经过对 2 (2 台服务器)取模运 ...

  9. 算法初级面试题05——哈希函数/表、生成多个哈希函数、哈希扩容、利用哈希分流找出大文件的重复内容、设计RandomPool结构、布隆过滤器、一致性哈希、并查集、岛问题

    今天主要讨论:哈希函数.哈希表.布隆过滤器.一致性哈希.并查集的介绍和应用. 题目一 认识哈希函数和哈希表 1.输入无限大 2.输出有限的S集合 3.输入什么就输出什么 4.会发生哈希碰撞 5.会均匀 ...

随机推荐

  1. /var/lib/zabbix/percona/scripts/get_mysql_stats_wrapper.sh: line 19: mysql: command not found

    [root@test ~]# tail -f /tmp/zabbix_agentd.log /var/lib/zabbix/percona/scripts/get_mysql_stats_wrappe ...

  2. 【设计模式】Java设计模式精讲之原型模式

    简单记录 - 慕课网 Java设计模式精讲 Debug方式+内存分析 & 设计模式之禅-秦小波 文章目录 1.原型模式的定义 原型-定义 原型-类型 2.原型模式的实现 原型模式的通用类图 原 ...

  3. 【MySql】[ERROR] Can't read from messagefile '/usr/share/mysql/english/errmsg.sys'

    [root@zhang bin]# ./mysql_install_db --datadir=/usr/local/mysql/mydata/data/ 2018-08-18 03:09:14 [WA ...

  4. 【EXP】WINDOWS下如何导出

    有些时候需要在windows下通过远程来导出数据 那么windows下怎么导出呢 例子: exp hr/hr@192.168.1.222:1521/zhang file=d:backup.dmp lo ...

  5. 【Oracle】Oracle 10g下载路径

    ORACLE 10g下载地址 下载方法: 直接复制下面的链接,打开迅雷,自动会识别下载的内容 Oracle Database 10g Release 2 (10.2.0.1.0) Enterprise ...

  6. 使用SimpleUpdater实现现有程序升级功能

    项目:https://github.com/iccfish/FSLib.App.SimpleUpdater C/S程式一般需要部署在多台机器上,如果程式有变动,需要一台一台重新安装,相当麻烦,如果我们 ...

  7. 前端基础功能,原生js实现轮播图实例教程

    轮播图是前端最基本.最常见的功能,不论web端还是移动端,大平台还是小网站,大多在首页都会放一个轮播图效果.本教程讲解怎么实现一个简单的轮播图效果.学习本教程之前,读者需要具备html和css技能,同 ...

  8. Docker 建站小记

    一,前言 Docker 建站小记,我使用了四个镜像来搭建:nginx,certbot,mysql,gradle.欢迎访问:https://www.zzk0.top 这个网页是从 github 上找的个 ...

  9. Jmeter-插件扩展及性能监控插件的安装

    需要对http服务进行大数据量的传值测试:看看产品中的http服务,能支持传多少字符:目标值是希望能到10w+: 上次测试中,服务器总是内存满导致服务不响应,因此想增加对服务端的性能监控:查阅了smi ...

  10. C语言中二维数组声明时,探究省略第一维的原因

    我们在使用二维数组作为参数时,我们既可以指明这个数组各个维度的维数,同时我们也可以省略一维,但是二维却不能省略.why呢?由于编译器原理的限制,在一个数组Elemtype test[m][n]中,访问 ...