Palindrome
问题描述:给你一个字符串,问至少需要添加几个字符才能形成回文串。
in:
5
Ab3bd
out:
2
解释如:dAb3bAd
做法:将给出的字符串反向存一遍,然后找最长公共子序列,用原长减去该长度就是需要添加的字符数
由于长度n为[3,5000];开5000的二维数组会mle,所以我们用滚动数组,由于状态转移方程告诉我们,
如果a[i]==b[j] 则 dp[i][j]=dp[i-1][j-1]+1
如果a[i]!=b[j] 则 dp[i][j]=max(dp[i-1][j],dp[i][j-1])
dp[i][j]的状态只能从相邻的两行之间转移,所以保证了滚动数组的有效性,但这里也有一个奇怪的地方,如果用std::string存字符串会RE,一直没有想明白,还请路过的大佬提点
if(a[i]==b[j]) dp[(i+1)%2][j+1]=dp[i%2][j]+1; else dp[(i+1)%2][j+1]=max(dp[i%2][j+1],dp[(i+1)%2][j]);
完整代码:
#include<stdio.h> #include<string.h> #include<iostream> #include<string> #include<algorithm> using namespace std; char a[5050],b[5050]; int dp[2][5020]; int main() { int n,i,j; while(~scanf("%d",&n)) { j=0; //cin>>a; scanf("%s",&a); for(i=0; i<n; i++) b[j++]=a[n-1-i]; for(i=0;i<n;i++) { for(j=0;j<n;j++) { if(a[i]==b[j]) dp[(i+1)%2][j+1]=dp[i%2][j]+1; else dp[(i+1)%2][j+1]=max(dp[i%2][j+1],dp[(i+1)%2][j]); } } printf("%d\n",n-dp[n%2][n]); //a.clear(); //b.clear(); memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); memset(dp,0,sizeof(dp)); } return 0; }