题目大意:
给一个字符串,求它最少需要添加几个字符变为回文串。
思路:
求出该字符串的逆序串,求两者之间的最长公共子序列的长度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;
}
结果: