动态规划步骤:
1、根据下面公式求出最大子序列的长度
C[i,j]为一个二维数组,用来保存子序列的长度
假设这两个序列分别是:X={A,B,C,B,D,A,B} Y={B,D,C,A,B,A}
长度分别为 m 和 n
得出最长子序列的长度为4
2、根据回溯法求出最长子序列
i和j分别从m,n开始,递减循环直到i = 0,j = 0。其中,m和n分别为两个串的长度。
·如果str1[i] == str2[j],则将str[i]字符插入到子序列内,i--,j--;
·如果str1[i] != str[j],则比较L[i,j-1]与L[i-1,j],L[i,j-1]大,则j--,否则i--;(如果相等,则任选一个)
接着我们来看一道题
题目描述:
给定一个字符串s,你可以从中删除一些字符,使得剩下的串是一个回文串。如何删除才能使得回文串最长呢?输出需要删除的字符个数
输入描述:
输入数据有多组,每组包含一个字符串s,且保证:1<=s.length<=1000.
输出描述:
对于每组数据,输出一个整数,代表最少需要删除的字符个数。
输入例子:
abcda
输出例子:
2
2
实现思想:
先保存字符串到str1
再保存字符串逆序后的结果到str2
求这两个序列的最大公共子序列,子序列的长度保存字二维数组C中
利用回溯法,求出最长公共子序列
#include <iostream>
#include <string>
#include <stack>
using namespace std;
void Reverse(char* first,char* second)
{
char tmp;
while (first < second){
tmp = *first;
*first = *second;
*second = tmp;
++first;
--second;
}
}
int main()
{
char s[1000];
while (cin >> s){
string str1(s);
/*string str2(s);
reverse(str2.begin(), str2.end());*/
Reverse(s,(s+str1.size()-1));
string str2(s);
//在str1、str2中找出最大公共子序列(LCS)
int m = str1.size();
int n = str2.size();
int* C = new int[ (m+1) * (n+1) ];//用来保存各子序列的长度
char* s1 = (char*)str1.c_str();
char* s2 = (char*)str2.c_str();
//填充二维数组C
for (int i = 0; i <= m; ++i){
for (int j = 0; j <= n; ++j){
if (i == 0 || j == 0){
C[i*(n+1) + j] = 0;
}
else{
if (*(s1 + i-1) == *(s2 + j-1)){
C [i*(n+1) + j] = C[(i-1)*(n+1) + j-1]+1;
}
else{
C[i*(n+1) + j] = (C[(i - 1)*(n+1) + j] > C[i*(n+1) + j - 1] ? C[(i - 1)*(n+1) + j] : C[i*(n+1) + j - 1]);
}
}
cout << C[i*(n + 1) + j] << " ";
}
cout << endl;
}
stack<char> stmp;
for (int i = m,j = n; i >= 0&&j>=0;){
if (*(s1 + i-1) == *(s2 + j-1)){
stmp.push(*(s1+i-1));
--i;
--j;
}
else{
*(C + i*(n + 1) + j - 1) > *(C + (i - 1)*(n + 1) + j )? --j : --i;
}
}
int size = str1.size() - stmp.size();
cout << size<<endl;
}
return 0;
}
转载于:https://blog.51cto.com/lingdandan/1846212