题目描述
回文串是指aba、abba、cccbccc、aaaa这种左右对称的字符串。每个字符串都可以通过向中间添加一些字符,使之变为回文字符串。
例如:abbc 添加2个字符可以变为 acbbca,也可以添加3个变为 abbcbba。方案1只需要添加2个字符,是所有方案中添加字符数量最少的。
输入
输入一个字符串Str,Str的长度 <= 1000。
输出
输出最少添加多少个字符可以使之变为回文字串。
输入样例
abbc
输出样例
2
题解:
题目的意思很简单,就是给定一个字符串,怎么添加最少的字符个数使之变成回文字符串,只是这么光想是想不出来的。
思路1:LCS
将一个字符串str反转之后得到字符串re_str,那么这两个字符串合到一起一定是回文串,比如
str = abbc,re_str = cbba,合到一起的字符串 = abbc cbba,这样就得到了回文字符串,但是其实并不需要添加这么多个长度,str和re_str可能会有公共子序列,比如这里的bb,那么再多加两个bb是不必要的,只要一个c和a即可,所以只要求出str的翻转字符串re_str,然后求两个字符串的LCS(最长公共子序列)即可,最后要添加的字符个数就是str.length() - LCS(str,re_str)
其实这里博主也不是很理解,也是看的别人的。
思路2:区间DP
(如果对区间DP不理解的同学可以去先百度下,其实我用的也很少,但是很好理解)
状态转移方程: 具体去看代码吧,代码中说的比较详细了。
if(str[i] == str[j])
{
dp[i][j] = dp[i+1][j-1];// 若第i个 == 第j个,说明这一对没问题,只要看里面的i+1 --- j-1
if(len == 2)
{
dp[i][j] = 0;// 长度为2的时候,上面的式子dp[i+1][j-1]是没有意义的,长度为2而且两个字符也相等,那添加的字符个数就为0
}
}
else
{
// 如果不相等,则选择i+1 --- j 和 i --- j-1的要添加字符串个数小的那一个,并且因为这里有一个字符不匹配,所以要+1,用来匹配第i个或者第j个
dp[i][j] = min(dp[i+1][j],dp[i][j-1]) + 1;
}
}
代码1:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
代码2:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include