题意:

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

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

Input

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

Output

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

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

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

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

    1..NetCore SDK版本问题 .NetCore3.1 webapi 部署linux,遇到一个坑,开启的目录浏览功能失效,几番尝试发现是版本问题.本地sdk版本与linux安装的sdk版本不对应 ...

  2. leetcode 321. 拼接最大数(单调栈,分治,贪心)

    题目链接 https://leetcode-cn.com/problems/create-maximum-number/ 思路: 心都写碎了.... 也许就是不适合吧.... 你是个好人... cla ...

  3. Netty中使用的设计模式

    创建型 简单工厂 public class DefaultThreadFactory implements ThreadFactory { @Override public Thread newThr ...

  4. java 文件上传的那些事

    文件上传 逻辑 @Value("${sava_path}") private String sava_path; @Override public String saveFile( ...

  5. 3A的限流芯片PW1503

    PW1503是超低RDS(ON)开关,具有可编程的电流限制,以保护电源于过电流和短路情况.它具有超温保护以及反向闭锁功能. PW1503采用薄型(1毫米)5针薄型SOT封装,提供可调版本. 特征    ...

  6. 处理 K8S Orphaned pod found - but volume paths are still present on disk 孤儿pod

    问题概述 查看kubelet或/var/log/messages日志一直包错,发现是孤儿pod,是由于其pod被删除后存储路径还保存在磁盘. 报错如下 [root@node5 ~]# journalc ...

  7. GRPC Health Checking Protocol Unavailable 14

    https://github.com/grpc/grpc/blob/master/doc/health-checking.md GRPC Health Checking Protocol Health ...

  8. 研发流程 接口定义&开发&前后端联调 线上日志观察 模型变动

    阿里等大厂的研发流程,进去前先了解一下_我们一起进大厂 - SegmentFault 思否 https://segmentfault.com/a/1190000021831640 接口定义 测试用例评 ...

  9. 控制反转 依赖注入 main函数

    通过依赖注入.服务定位实现控制反转 Go kit - Frequently asked questions https://gokit.io/faq/ Dependency Injection - W ...

  10. 使用Linux服务器来通过网络安装和激活Windows 7 —— 一些基本原理

    使用Linux服务器来通过网络安装和激活Windows 7 -- 一些基本原理 https://www.pufengdu.org/blog/?p=372