回文字符串
时间限制:
3000 ms | 内存限制:
65535 KB
难度:
4
描述
所谓回文字符串,就是一个字符串,从左到右读和从右到左读是完全一样的,比如"aba"。当然,我们给你的问题不会再简单到判断一个字符串是不是回文字符串。现在要求你,给你一个字符串,可在任意位置添加字符,最少再添加几个字符,可以使这个字符串成为回文字符串。
输入
第一行给出整数N(0<N<100)
接下来的N行,每行一个字符串,每个字符串长度不超过1000.
输出
每行输出所需添加的最少字符数
样例输入
1
Ab3bd
样例输出
2
这道题一开始看一脸懵逼,不知道要干嘛,上网查了查发现具体做法如下:
1.先获得字符串的翻转字符串
2.获得这两个字符串的最大子序列(可以不连续)
http://blog.chinaunix.net/uid-26548237-id-3374211.html 此为求最长子序列
3.字符串的长度减去最大子序列的长度就是答案
看起来很简单,代码写起来也很简单,但是就是要理解
这么理解,原先的字符串的回文的,然后被挖去几个字符,被挖去的字符和他对称的字符串可以理解为换成了空格
翻转的字符串和原先字符串的最长公共子序列就是原先的回文字符串去除掉某些字符或后剩下的仍然是回文的部分,只不过因为被挖去了,位置上不回文
原先的字符串长度减去最长公共子序列的长度就是那些被挖去的字符的长度
#include<iostream>
#include<algorithm>
#include<vector>
#include<stack>
#include<string.h>
#include<string>
#include<memory.h>
using namespace std;
int L[1001][1001];
int main()
{
int N, i, j;
string str, str2;
cin >> N;
while (N--){
cin >> str;
str2 = str;
reverse(str2.begin(), str2.end()); //获得str的翻转字符串
memset(L, 0, sizeof(L));
for (i = 1; i <= str.length();i++)
for (j = 1; j <= str.length(); j++){
if (str[i - 1] == str2[j - 1]) L[i][j] = L[i - 1][j - 1] + 1;
else{
L[i][j] = max(L[i - 1][j], L[i][j - 1]);
}
}
cout << str.length() - L[str.length()][str.length()] << endl;;
}
return 0;
}