题目大意:
给一个字符串,求它最少需要添加几个字符变为回文串。
思路:
求出该字符串的逆序串,求两者之间的最长公共子序列的长度len,再用该字符串的长度strLen-len即得到最少需要添加的字符的个数,本题得解。
最长公共子序列的思路:
int a[]={1,2,4,5,7}; len_a=5; i=len_a;i--;i指向7然后是5,4,2,1;
int b[]={1,4,5};len_b=3;j=len_b;j--;j指向5然后是4最后是1;
如果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]);
AC代码如下:
#include<iostream> #include<stdio.h> #include<stdlib.h> #include<string.h> #include<cstring> int dp[1005][1005]; using namespace std; int main() { int n; scanf("%d",&n);//n组数据 while(n--) { memset(dp,0,sizeof(dp)); string a; cin>>a;//输入字符串 int len=a.length(); string b="";//将a的反串存到b中,可使用别的函数 for(int i=len-1;i>=0;i--) { b+=a[i]; } for(int i=1;i<=len;i++)//求a和b的最长公共子序列的长度 { for(int j=1;j<=len;j++) { if(a[i-1]==b[j-1]) dp[i][j]=dp[i-1][j-1]+1; else dp[i][j]=dp[i-1][j]>dp[i][j-1]?dp[i-1][j]:dp[i][j-1]; } } int max=0; for(int i=0;i<=len;i++) { for(int j=0;j<=len;j++) { if(max<dp[i][j]) { max=dp[i][j]; } } } printf("%d\n",len-max);//输出结果 } return 0; }
求一个字符串的反串儿可以直接用reverse(a.begin(),a.end())函数或者assign(a.begin(),a.end())而不是用for循环:
1、将a自身翻转, std:: void reverse(a.begin(), a.end());
2、将a反转到b里面, s1.assign(a.rbegin(), a.rend());
例子:
#include<iostream> #include<stdio.h> #include<stdlib.h> #include<cstring> #include<algorithm> using namespace std; int main() { string a;string b; a="abcdefg"; cout<<"原始"<<a<<" "<<b<<endl; b.assign(a.rbegin(),a.rend());//b将变为“gfedcba”,a不变 cout<<"改变b:"<<a<<" "<<b<<endl; reverse(a.begin(),a.end());//a将变为“gfedcba” cout<<"改变a:"<<a<<" "<<b<<endl; return 0; }
结果: