http://acm.nyist.net/JudgeOnline/problem.php?pid=37
有两种方法,第一种是先把字符串翻转,得到一个新的字符串,分别表示为a ,b ,然后求出 a 和 b 的最长公共子序列 len ,最后用a 串的长度减去 len 即可。
#include"iostream"
#include"stdio.h"
#include"string"
#include"cstring"
#include"cmath"
#include"algorithm"
#include"stdlib.h"
using namespace std;
int dp[1010][1010];
char a[1010],b[1010];
/*
dp[i][j] 用来表示以 a 串以i 字母结尾,b 串以j 字母结尾时两串公共子序列的长度。
*/
int getlen(int len)
{
int i ,j;
for(i = 1; i <= len; i++)
for(j = 1; j <= len; j++)
{
if(a[i-1] == b[j-1]) dp[i][j] = dp[i-1][j-1] + 1;
else
{
dp[i][j] = max(dp[i-1][j] ,dp[i][j-1]);
}
}
return dp[len][len];
}
int main()
{
int N;
cin>>N;
while(N--)
{
int i,j;
memset(dp,0,sizeof(dp));
cin>>a;
int len = strlen(a);
for(i = len - 1,j = 0; i >= 0; i--)
b[j++] = a[i];
//for(i = 0; i < len; i++)
//cout<<b[i]<<endl;
cout<<len - getlen(len)<<endl;
}
return 0;
}
第二种方法:开设一个数组 dp[i][j] 用来表示已 第 j 个字母开始,长度为 i 的序列变成回文串所需要的最小的添加数 。
#include"iostream"
#include"stdio.h"
#include"string"
#include"cstring"
#include"cmath"
#include"algorithm"
#include"stdlib.h"
using namespace std;
int dp[1010][1010];
/*
dp[i][j] 用来表示已 第 j 个字母开始,长度为 i 的序列变成回文串所需要的最小的添加数
*/
int main()
{
int N;
string s;
cin>>N;
while(N--)
{
int i,j;
memset(dp,0,sizeof(dp));
cin>>s;
int len = s.size();
for(i = 0; i < len; i++)
dp[0][i] = dp[1][i] = 0;
for(i = 2; i <= len; i++)
for(j = 0; j < len; j++)
{
if(s[j] == s[j+i-1]) dp[i][j] = dp[i-2][j+1];
else
dp[i][j] = min(dp[i-1][j],dp[i-1][j+1]) + 1;
}
cout<<dp[len][0]<<endl;
}
return 0;
}
本文介绍了解决最短回文串问题的两种方法:一是通过计算字符串与其反转后的最长公共子序列;二是使用动态规划算法来确定使序列成为回文所需的最小添加数。
759

被折叠的 条评论
为什么被折叠?



