题目:给你一个字符串,可以进行增删改三种操作,问变成回文串最少的操作次数。
分析:动态规划,dp,LCS。可以利用区间dp求解,这里利用LCS求解更快。
利用字符串和自己的翻转求最大公共子序列,然后枚举所有的dp[i][len-i],
找最小的即可。注意可能最小值在dp[i-1][len-i],即str[i]为中间元素,不用匹配。
说明:注意dp的初始化赋值。
#include <cstring>
#include <cstdio>
int dp[1001][1001];
int main()
{
int n;
char str1[1001],str2[1001];
while (~scanf("%d",&n))
for (int t = 1; t <= n; ++ t) {
scanf("%s",str1);
int len = strlen(str1);
for (int i = 1; i <= len; ++ i)
str2[i-1] = str1[len-i];
//初始条件
for (int i = 0; i <= len; ++ i)
dp[i][0] = dp[0][i] = i;
for (int i = 1; i <= len; ++ i)
for (int j = 1; j <= len; ++ j) {
if (str1[i-1] == str2[j-1])
dp[i][j] = dp[i-1][j-1];
else
dp[i][j] = dp[i-1][j-1]+1;
if (dp[i][j] > dp[i][j-1]+1)
dp[i][j] = dp[i][j-1]+1;
if (dp[i][j] > dp[i-1][j]+1)
dp[i][j] = dp[i-1][j]+1;
}
int min = len;
for (int i = 1; i < len; ++ i) {
if (min > dp[i-1][len-i])
min = dp[i-1][len-i];
if (min > dp[i][len-i])
min = dp[i][len-i];
}
printf("Case %d: %d\n",t,min);
}
return 0;
}