修改回文(二)
内存限制: 256 Mb时间限制: 1000 ms
题目描述
给定一个仅由小写字母组成的字符串 s ,你可以添加一些字符(也可以不加),使其构成回文串。
请你输出在添加字符数最少的前提下,能够构成字典序最小的回文串。
输入格式
输入共一行,一个字符串 s
输出格式
输出共一行,题目所求的回文串。
数据范围
设 ∣s∣ 为字符串 s 的长度,则有:
- 对于 30% 的数据,1≤∣s∣≤10
- 对于 60% 的数据,1≤∣s∣≤100
- 对于 100% 的数据,1≤∣s∣≤10^3
样例数据
输入:
ai
输出:
aia
说明:
字符串ai至少添加一个字符构成回文,该前提下,可以构造成aia、iai,但aia的字典序更小
输入:
iai
输出:
iai
说明:
不用添加任何字符
输入:
abca
输出:
abcba
解析:使用动态规划的方法,详见代码:
#include<bits/stdc++.h>
using namespace std;
//dp[i][j]为从i开头到j结尾添加字符后的最小回文串
//为节省空间,将i为奇数存入dp[1][j],偶数存入dp[0][j];
string dp[2][3005];
string s;
int len;//字符串长度
int main() {
cin >> s;
len = s.length();
for(int i = len - 1; i >= 0; i--) {//枚举所有开头为i,结尾为j的子串
for(int j = i; j < len; j++) {
if (i == j) {//单个字符,自己即为回文串
dp[i % 2][j] = s[i];
} else if (s[i] == s[j]) {//头尾相同,都加头或尾
dp[i % 2][j] = s[i] + dp[(i + 1) % 2][j - 1] + s[j];
} else {//头尾不同
//都加头
string t1 = s[i] + dp[(i + 1) % 2][j] + s[i];
//都加尾
string t2 = s[j] + dp[i % 2][j - 1] + s[j];
//取最小值
if (t1.length() > t2.length()) {
dp[i % 2][j] = t2;
} else if (t1.length() < t2.length()) {
dp[i % 2][j] = t1;
} else {
dp[i % 2][j] = min(t1, t2);
}
}
}
}
cout << dp[0][len - 1];
return 0;
}