回文字符串
时间限制:
3000 ms | 内存限制:
65535 KB
难度:
4
-
描述
-
所谓回文字符串,就是一个字符串,从左到右读和从右到左读是完全一样的,比如"aba"。当然,我们给你的问题不会再简单到判断一个字符串是不是回文字符串。现在要求你,给你一个字符串,可在任意位置添加字符,最少再添加几个字符,可以使这个字符串成为回文字符串。
-
输入
-
第一行给出整数N(0<N<100)
接下来的N行,每行一个字符串,每个字符串长度不超过1000.
输出
- 每行输出所需添加的最少字符数 样例输入
-
1 Ab3bd
样例输出
-
2
-
刚开始看到这道题,看了一会没看出头绪,然后看人家说是要用动态规划里面的最长公共子序列,可是还是想不出为什么。后来同学同学问我这道题,就仔细的想了想。结果发现还真是。
-
思路:题目中是要求将字符串补成回文串时最少补充的字符。那么我们可以这样想,我们先有一个回文串,然后故意去掉几个。。。就成了题目中的测试案例。
-
然后呢,假设去掉的那些字符我们保留为空格,我们想,既然之前是回文的,当我们反转过来背去掉剩下的,然后去掉空格,必然会有些字符还是匹配的,这部分匹配的就是不用动的部分,一个字符串当作模式串,一个当作匹配串,从头到尾匹配,总有一种情况下匹配的字符达到最大,这便是我们把他们变回回文串时不用改动的最大数值,然后根据题意,只要我们拿字符串的总长度减去这个数,便是需要改动的最少个数。也就转化成了求最长公共子序列问题。
-
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
-
对案例:asdfgg 进行的测试。#include<iostream> #include<string> #include<cstring> using namespace std; char *reverse( char a[]) { char *b=new char[1005]; int t=strlen(a); int i,j; for(i=t-1,j=0;i>=0;j++,i--){ b[j]=a[i]; } return b; } int dp[1000][1000]; int main() { int n; cin>>n; while(n--) { char a[1005]; cin>>a; int str = strlen(a); string b=reverse(a); //cout<<b<<endl; for(int i =0;i <= str;i ++){ for(int j =0 ;j <= str; j++){ if(i == 0||j == 0) dp[i][j]=0; else if(b[i-1] == a[j-1]) dp[i][j]=dp[i-1][j-1]+1; else dp[i][j]=max(dp[i-1][j],dp[i][j-1]); } } /*for(int i = 0; i <= str; i ++){ for(int j = 0;j <= str; j++){ cout<<dp[i][j]<<" "; } cout<<endl; }*/ cout<<str-dp[str][str]<<endl; } return 0; }
-
看下图,理解最长公共子序列
-
案例是:ACDDEB和ADC
-
-
-
第一行给出整数N(0<N<100)