从一个看来的题目想起来的,说,有一个无序字符串,如何挑出最少的元素,让余下的部分变成一个有序串。
没想到方法,给的答案是:将字符串排序,找出排序后的字符串和原字符串的最长公共子序列,
因为子序列是不要求连续的,所以不能用最长公共子串的算法,
思路:
建立一个矩阵,从后往前推,如果 a[i] == b[j],那么最长公共子序列肯定要包含这一格;否则的话,最长公共子序列就是 max{a[i-1], b[j-1]},
代码:
#include <iostream>
using namespace std;
void func(char* s1, char *s2){
int l1 = strlen(s1), l2 = strlen(s2);
int arr[l1+1][l2+1];
//第一行和第一列都用来放 0 ,
memset(arr, 0, sizeof(arr));
int m =0, n = 0;
for(int m = 0; m < l1; ++m){
for(int n = 0; n < l2; ++n){
if(s1[m] == s2[n])
arr[m+1][n+1] = arr[m][n] +1;
else
arr[m+1][n+1] = (arr[m][n+1]>arr[m+1][n])? arr[m][n+1] : arr[m+1][n];
}
}//建立矩阵
for(m = 0; m <= l1; ++m){
for(n = 0; n <= l2; ++n){
cout << arr[m][n] << " ";
}
cout << endl;
}//输出矩阵,看的直观点,
m = l1, n = l2;
while(arr[m][n] != 0){
if( (arr[m][n] = arr[m-1][n-1] +1) && (arr[m][n-1] == arr[m-1][n] ) && (arr[m][n-1] == arr[m-1][n-1])){
//条件判别,如果在矩阵中,这个值的上,左,左上都比它小,那么这个店肯定是个相同的点,
//所以就输出这个值,然后向左上走一格
cout << s1[m-1];
m = m-1, n = n-1;
}
else{
if(arr[m][n-1] == arr[m][n])
m = m, n = n-1;
else
n = n, m = m-1;
//此处之所以要判断,只要是为了应付边界情况下, 防止出界
}
}//输出的是逆序的,暂时不care
cout << endl;
}
int main(){
char s1[] = "ABCBDAB", s2[] = "BDCABA";
func(s1, s2);
system("pause");
return 0;
}
windows下dev cpp通过,如果放到 Linux 下肯定一堆报错,各种没包含,就这样吧,