【算法设计与分析】5、最长公共子序列

来源:互联网 发布:国联证券软件下载 编辑:程序博客网 时间:2024/06/07 17:51
/*** 书本:《算法分析与设计》* 功能:若给定序列X={x1, x2, ..., xm},则另一序列Z={z1, z2, ..., zk},是X的子序列是指存在一个严格递增下标序列{i1, i2, ..., ik}*      使得对于所有j=1,2,。。。,k有:zj=xij.给定两个序列X={x1, x2, ... xm}和Y={y1, y2, ..., yn}找出X和Y的最长公共子序列* 文件:MostLength.cpp* 时间:2014年11月25日18:23:29* 作者:cutter_point*/#include <iostream>#define MAXLEN 100using namespace std;//这是一个求得最长子序列的长度的函数//X和Y是两个序列,m和n是长度,c是存放的结果,b是对应的序列序号下之间最长子序列的结构情况//最长子序列分三种最优子结构/*  {0   i=0, j=0c[i][j] = {c[i-1][j-1]+1   i,j > 0; Xi == Yj 第一类  {max{c[i][j-1], c[i-1][j]}  i,j > 0; Xi != Yj 第二和第三类,大小关系分为两类*/void LCSLength(char *x, char *y, char *z, int m, int n, int c[][MAXLEN], int b[][MAXLEN]){int i, j;//用来标记下标,对应x和y中对应的数//首先初始化x和y中第0个匹配的长度为0for (i = 1; i <= m; ++i) c[i][0] = 0;//c[i][0] = 0;//然后初始化x中第0个和y的最长公共子序列长度for (i = 1; i <= n; ++i) c[0][i] = 0;//int l = 1;//用来计数第二个序列比较到了第几个数//char change = ' ';//用来记住第一次比较到的字符,如果第二次还得到这个就不重复计数//然后把x中每一个元素和y中的每一个元素相匹配for (i = 1; i < m; ++i){for (j = 1; j < n; ++j)//y中每一个元素,从上面一个循环中比较到的个数开始比较{if (x[i] == y[j])//如果对应的元素相等,那么就把长度+1{c[i][j] = c[i - 1][j - 1] + 1;//长度是前面的最长度+1,第一类子结构//l = j+1;//用来计数第二个序列比较到了第几个数,而且这里应该只计数第一次出现的地方z[i] = x[i];//change = x[i];//重新得到一个新的比较计数器b[i][j] = 1;//就是x中第i个和y中第j个的长度中的最长子序列的结构式第一类子结构//如果找到了和这个一样的子序列,那么就跳出//break;}else if (c[i - 1][j] >= c[i][j - 1])//去掉这个xi剩下的最长子序列和去掉yj剩下的最长子序列的大小比较{//如果是最长子序列去掉xi的那个长的话,那么就取这个数c[i][j] = c[i - 1][j];b[i][j] = 2;//就是x中第i个和y中第j个的长度中的最长子序列的结构式第二类子结构}else{//如果是最长子序列去掉yj的那个长的话,那么就取这个数c[i][j] = c[i][j - 1];b[i][j] = 3;   //就是x中第i个和y中第j个的长度中的最长子序列的结构式第三类子结构}}}}//划分,每次根据上面得到的每层的最优子结构类型划分,来进行不同的操作//这里i和j分别是是x和y对应的第i个j个元素,x就是比较长的那个序列,b是上面求得的结构层次/*{0   i=0, j=0c[i][j] ={c[i-1][j-1]+1   i,j > 0; Xi == Yj 第一类{max{c[i][j-1], c[i-1][j]}  i,j > 0; Xi != Yj 第二和第三类,大小关系分为两类*///这里参数i和j表示这两个序列拥有的元素个数void LCS(int i, int j, char *x, int b[MAXLEN][MAXLEN]){if (i == 0 || j == 0) return;//如果序号都是0,那么就不用匹配了if (b[i][j] == 1)//结构是第一类的时候,说明xi和yj相等{LCS(i - 1, j - 1, x, b);//这个就是x和y都已经找到一个相等的子元素了,那就只有剩下的没有输出了//输出那个子元素cout << x[i] << " ";}else if (b[i][j] == 2)//结构是第二类的时候,说明xi比yj大{LCS(i - 1, j, x, b);//这是第二种情况,那就把那个大去掉,求剩下的几个的最长子序列}else//结构是第三类的时候,说明xi比yj大{LCS(i, j - 1, x, b);  //这是第三种情况,那就把那个大去掉,求剩下的几个的最长子序列}}int main(){char x[] = { ' ', 'a', 'x', 'b', 'g', 't', 'c', 'f', 'd', 'g', 'a', 'e', 'f' };char y[] = { ' ', 'j', 'a', 'b', 'j', 't', 'j', 'c', 'l', 'd', 'a', 'f' };char z[MAXLEN] = {'.'};const int m = sizeof(x) / sizeof(x[0]);const int n = sizeof(y) / sizeof(y[0]);//X和Y是两个序列,m和n是长度,c是存放的结果,b是对应的序列序号下之间最长子序列的结构情况int c[MAXLEN][MAXLEN] = {0};int b[MAXLEN][MAXLEN] = {0};LCSLength(x, y, z, m, n, c, b);//输出相应的长度序列//cout << "这是什么!" << endl;//for (int k = 0; k <= n; ++k)//cout << k << " " << endl;for (int i = 1; i < m; ++i){cout << i << " "<<endl;for (int j = 1; j < n; ++j){if (c[i][j] != 0){cout << "X序列中前" << i << " 到Y序列中前" << j << " 的公共子序列:" << c[i][j] << " " << endl;}}cout << endl;}/*//求出b的值for (int i = 1; i < m; ++i){for (int j = 1; j < n; ++j)cout << b[i][j] << " ";cout << endl;}2 1 3 32 2 2 22 2 1 3//求出Cfor (int i = 1; i < m; ++i){for (int j = 1; j < n; ++j)cout << c[i][j] << " ";cout << endl;}0 1 1 10 1 1 10 1 2 2*/cout << "最长公共子序列是:" << endl;LCS(m-1, n-1, x, b);cout << endl;return 0;}

0 0
原创粉丝点击