今天看了一下动态规划的思想,基本最基本的问题就是背包、硬币、lcs。lcs在解决字符串相似度上比较常用,属于算法中的基础,我还没有掌握,自己得有多么多么水呀,但没关系今天之后你掌握了,你就向成功程序员向前走了一步。
动态规划
既然是经典的题目肯定是有优化空间的,并且解题方式是有固定流程的,这里我们采用的是矩阵实现,也就是二维数组。
第一步:先计算最长公共子序列的长度。
第二步:根据长度,然后通过回溯求出最长公共子序列。
现有两个序列X={x1,x2,x3,...xi},Y={y1,y2,y3,....,yi},
设一个C[i,j]: 保存Xi与Yj的LCS的长度。
递推方程为:
根据这个递推公式,利用两个for循环,就可以求出lcs的最大长度,主要就是先初始化周围的两排需要用的数据,之后递推推导出数组中所有的值,最后遍历一遍就可以知道最大值。如果想知道序列的内容,就要加上标记,如果数组的值都有三种选择,c[i-1][j-1]可以标记位左上,c[i-1][j]可以标记位左,c[i][j-1]可以标记位上,之后寻找左上这个序列就OK了。
回溯输出最长公共子序列过程:
算法分析:
由于每次调用至少向上或向左(或向上向左同时)移动一步,故最多调用(m + n)次就会遇到i = 0或j = 0的情况,此时开始返回。返回时与递归调用时方向相反,步数相同,故算法时间复杂度为Θ(m + n)。
代码:
#include <stdio.h>
#include <string.h>
#define MAXLEN 100
void LCSLength(char *x, char *y, int m, int n, int c[][MAXLEN], int b[][MAXLEN])
{
int i, j;
for(i