problem
一个字符串如果从左往右读和从右往左读都一样,那么这个字符串是一个回文串。例如:abcba
,abccba
。
蕊蕊想通过添加字符把一个非回文字符串变成回文串。例如:"mecm"
,可以添加一个e
,变成回文串"mecem"
。请你用程序计算出,对于一个给定的字符串,最少需要添加几个字符,才能变成回文串。
输入格式
输入一个长度为 n(1≤n≤3000) 的字符串。(字符串只包含字母)
输出格式
输出最少需要添加的字符个数,占一行。
样例输入
trit
样例输出
1
思路
回文串的顺序倒转后,与原串是一样的。
那么我们只要把给定的字符串顺序倒转与原串求最长公共子序列,再用字符串总长度减去最长公共子序列的长度就是相差的字符个数,也就是答案
比如mecm和mcem的LCS是mem或mcm
可以添加一个e
凑成 mecem
也可以添加一个c
凑成 mcecm
因此,用字符串总长度减去最长公共子序列的长度即为最少需要添加的字符数
代码示例
#include<bits/stdc++.h>
using namespace std;
const int maxn=3010;
string s1,s2;
int len1,len2;
int dp[maxn][maxn];
int solve()//LCS
{
for(int i=1;i<=len1;++i){
for(int j=1;j<=len2;++j){
if(s1[i-1]==s2[j-1]){
dp[i][j]=dp[i-1][j-1]+1;
}
else dp[i][j]=max(dp[i][j-1],dp[i-1][j]);
}
}
return dp[len1][len2];
}
int main()
{
ios::sync_with_stdio(false);
cin>>s1;
len1=(int)s1.length();
//string逆置
s2=s1;
reverse(s2.begin(),s2.end());
//string逆置
//s2.assign(s1.rbegin(),s1.rend());
len2=s2.length();
cout<<len1-solve()<<endl;
return 0;
}