注:
- 最长公共子序列采用动态规划解决,由于子问题重叠,故采用数组缓存结果,保存最佳取值方向。输出结果时,则自顶向下建立二叉树,自底向上输出,则这过程中没有分叉路,结果唯一。
- 最长公共子串采用参考串方式,逐步比对,若相同则对应参考值自增,同时记录当前时刻最大参考值,及其位置。最后输出多组结果。
源码:lcs.cpp
#include "stdafx.h" #include <stdio.h> #include <vector> /************************************************************************/ /* 最长公共子序列 / 最长公共子串 */ /* lcseq / lcstr */ /************************************************************************/ //注意!需要输出多组结果! int length(char *pstr) { int i; i = 0; while (*pstr++) i++; return i; } void print_matrix(int **mat, char *x, char *y, int m0, int n0, int m, int n) { int i, j; printf(" "); for (j = 0; j < n; j++) { printf("%-3c", y[j]); } printf(" "); for (i = m0; i < m; i++) { printf("%-4c", x[i - m0]); for (j = n0; j < n; j++) { printf("%-3d", mat[i][j]); } printf(" "); } } /* * > 子串是串的一个连续的部分 * > 子序列则是不改变序列的顺序,而从序列中去掉任意的元素而获得新的序列 * > 【也就是说,子串中字符的位置必须是连续的,子序列则可以不必连续。】 */ struct node { int parent; char c; }; //************************************ // Method: 构建二叉树 // FullName: build_btree // Access: public // Returns: void // Qualifier: // Parameter: char * x 原始字符串X // Parameter: int * * mat 跟踪矩阵 // Parameter: int m 串X长度 // Parameter: int n 串Y长度 // Parameter: int parent 父结点ID // Parameter: std::stack<node> & tree 树 //************************************ void build_btree(char *x, int **mat, int m, int n, int parent, std::vector<node>& tree) { if (m == -1 || n == -1)//跟踪到叶子结点,可以打印 { int i; for (i = parent; i != -1; i = tree[i].parent) { char c; c = tree[i].c; if (c) { printf("%c", c); } } printf(" "); return; } if (m == 0 && n == 0)//处理左上角结点的情况Z(0,0) { build_btree(x, mat, -1, -1, parent, tree); return; } int p = mat[m][n]; if (mat[m][n] == 0)//防止访问重复结点 return; mat[m][n] = 0; node newnode; newnode.c = '