最长公共子序列的问题很简单,就是在两个字符串中找到最长的子序列,这里明确两个含义:
- 子串:表示连续的一串字符 。
- 子序列:表示不连续的一串字符。
所以这里要查找的是不连续的最长子序列,
这里为什么要使用动态规划可以说一下,简单来说动态规划是为了降低时间复杂度的一种算法,申请一个额外空间,来保存每一个步骤的结果,最后从这些结果中找到最优的解。
这里有个问题就是:一般来说,当前的最优解,只与当前时刻和上一时刻有关系,和其他时刻没有关系,这样才能让动态规划发生作用,降低复杂度。
其实LCS看起来很麻烦,找不到思路,如果暴力破解可能要O(n^4)了,而这个题目使用动态规划的思想也非常简单,为何相比之前的问题不好找思路呢?
是因为之前的动态规划问题例如:背包问题,生产线问题,都是一维数组空间内的结果,规划到一个线性时间内,而这个题目需要O(m*n)的时间复杂度和空间复杂度。
所以其实就是进行
m*n
次对比,每次保存当前的最优解,就可以了。
这里有个问题,就是我们需要的结果仅仅是长度? 还是包括这个序列串一起输出。
看下面图:
这里可以看到,我们构造的一个i*j
的矩阵,这个矩阵里的内容不但包括数值(当前结果的最优解),还包括一个方向箭头,这个代表了我们回溯的时候,需要行走的方向。
所以我们这里保存两个值,可以使用两个二维矩阵,也可以使用一个结构体矩阵。
其实这个题目在动态规划来理解,也非常简单。一个状态转移函数。
这个非常好理解,其中一个字符串为0的时候,那么肯定是0了。
当两个字符相等的时候,这个时候很好理解,举例来说:
abcd
和 adcd
,在遍历c
的时候,发现前面只有a
相等了,也就是1.
那么c
相等,也就是abc
和adc
在匹配的时候,一定比ab
和ad
的长度大1
,这个1
就是c
相等么。也就是相等的时候,是比c[i-1][j-1]
大1
的。
下一个更好理解了,如果不相等,肯定就是找到上一个时刻对比最大的么。
这个代码只输出了LCS的长度,而结果数组的方向我已经存储好了,想要遍历的,直接从后向前遍历数组就好了。
//
// main.cpp
// LCS
//
// 最长公共子序列(LCS)
//
// Created by Alps on 15/8/23.
// Copyright (c) 2015年 chen. All rights reserved.
//
#include <iostream>
using namespace std;
/*
* 这里可以不定义长度,输入的字符串用string存储,然后利用string.c_str()来对字符串进行数组转化。 我这里为了方便没有这样做。
*/
#ifndef MAX_LENGTH
#define MAX_LENGTH 15 //定义字符串最大长度
#endif
int MaxNum(int firstNum, int secondNum){
return firstNum > secondNum ? firstNum : secondNum;
}
//定义数组结构体
struct matrix{
int num;
int direct;
};
typedef matrix Matrix;
int LCS(char *strA, char *strB, int lengthA, int lengthB, Matrix *resultMatrix[]){
if (lengthA == 0 || lengthB == 0) {
return 0;
}
for (int i = 0; i < lengthA; i++) {
for (int j = 0; j < lengthB; j++) {
resultMatrix[i][j].num = 0; //设置所有默认的最长为0
resultMatrix[i][j].direct = 1; //所有默认方向变成上 0斜上,1上,-1左
}
}
for (int i = 0; i < lengthA; i++) {
for (int j = 0; j < lengthB; j++) {
if (strA[i] == strB[j]) {
resultMatrix[i+1][j+1].num = resultMatrix[i][j].num + 1;
resultMatrix[i+1][j+1].direct = 0;
}else{
resultMatrix[i+1][j+1].num = MaxNum(resultMatrix[i+1][j].num, resultMatrix[i][j+1].num);
resultMatrix[i+1][j+1].direct = resultMatrix[i+1][j].num > resultMatrix[i][j+1].num ? 1 : -1;
}
}
}
return resultMatrix[lengthA][lengthB].num;
}
int main(int argc, const char * argv[]) {
char *strA = (char*)malloc(sizeof(char) * MAX_LENGTH);
char *strB = (char*)malloc(sizeof(char) * MAX_LENGTH);
scanf("%s",strA);
scanf("%s",strB);
int lengthA = (int)strlen(strA);
int lengthB = (int)strlen(strB);
Matrix *resultMatrix[lengthA+1];
for (int i = 0; i <= lengthA; i++) {
resultMatrix[i] = (Matrix*)malloc(sizeof(struct matrix)* (lengthB+1));
}
int max = LCS(strA, strB, lengthA, lengthB, resultMatrix);
printf("%d\n",max);
std::cout << "Hello, World!\n";
return 0;
}
以上。?Alps1992
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/alps1992/article/details/47923041