51nod 1092 回文字符串【LCS】
基准时间限制:1 秒 空间限制:131072 KB 分值: 10 难度:2级算法题
收藏
关注
回文串是指aba、abba、cccbccc、aaaa这种左右对称的字符串。每个字符串都可以通过向中间添加一些字符,使之变为回文字符串。
例如:abbc 添加2个字符可以变为 acbbca,也可以添加3个变为 abbcbba。方案1只需要添加2个字符,是所有方案中添加字符数量最少的。
Input
输入一个字符串Str,Str的长度 <= 1000。
Output
输出最少添加多少个字符可以使之变为回文字串。
Input示例
abbc
Output示例
2
[分析]:求逆串与原串的最长公共子序列(可不连续),结果就为字符串长度-最长公共子序列长度。
[代码]:
#include<bits/stdc++.h> #define ll long long using namespace std; const int maxn=1010; string a,b; int dp[maxn][maxn]; int main(){ cin>>b; int n=b.size(); a=b; reverse(b.begin(),b.end()); for(int i=1;i<=n;++i){ for(int j=1;j<=n;++j){ if(a[i-1]==b[j-1]) //这里为什么要用i-1,j-1,因为str中的下标从0开始 dp[i][j]=dp[i-1][j-1]+1; else dp[i][j]=max(dp[i-1][j],dp[i][j-1]); } } cout<<n-dp[n][n]<<endl; return 0; }
#include<cstring> #include<cstdio> #include<cmath> #include<iostream> #include<algorithm> using namespace std; char a[1010],b[1010]; int f[1010][1010]; string s; int main() { scanf("%s",a+1); scanf("%s",b+1); int n=strlen(a+1); int m=strlen(b+1); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { if(a[i]==b[j]) f[i][j]=f[i-1][j-1]+1; else f[i][j]=max(f[i-1][j],f[i][j-1]); } int i=n,j=m; while(i && j) { if(a[i]==b[j]) { s+=a[i]; i--; j--; } else if(f[i][j]==f[i-1][j]) i--; else j--; } int len=s.length(); for(int i=len-1;i>=0;i--) printf("%c",s[i]); }