最长公共子序列

来源:互联网 发布:网络主播大秀在线视频 编辑:程序博客网 时间:2024/04/30 03:06

/*若给定序列X={x1,x2,…,xm},则另一序列Z={z1,z2,…,zk},是X的子序列是指存在一个严格递增下标序列{i1,i2,…,ik}使得对于所有j=1,2,…,k有:zj=xij。例如,序列Z={B,C,D,B}是序列X={A,B,C,B,D,A,B}的子序列,相应的递增下标序列为{2,3,5,7}。 •给定2个序列X和Y,当另一序列Z既是X的子序列又是Y的子序列时,称Z是序列X和Y的公共子序列。

•给定2个序列X={x1,x2,…,xm}和Y={y1,y2,…,yn},找出X和Y的最长公共子序列。

*/

/**********************************************************************
  REVISION LOG ENTRY
  Revision By:
http://blog.csdn.net/hongweijin
  Revised on 2005-3-23 16:39:35
  Comments: 最长递增序列的动态规划法实现,如序列
   1    3   7   4   8   2   9   0   4
   其最长子递增序列为:
            1 3 4 8
 *********************************************************************/


#include <stdio.h>
#include <stdlib.h>

int  CreatList(int Source[]);
void GetLongestList(int Source[], int length);

void main()
{
 int Source[100];
 int length;

 length = CreatList(Source);
 GetLongestList(Source, length);
}


///////////////////////////////////////////////////////////////////////
//
// 函数名       : GetLongestList
// 功能描述     : 得到最长递增子序列
// 参数         : int Source[]
// 参数         : int length
// 返回值       : void
//
///////////////////////////////////////////////////////////////////////
void GetLongestList(int Source[], int length)
{
 int i, j, nextj,  * Max, * temp,  client = 0, lenTemp;
 ///////////////////////////////////////////////////////////////////
 // Max求值算法:
 //  通过“动态规划法”:在左面选择一个 ,假设这个点在
 //  最长子序列里面,那么我可以知道,问题被分成两个部分,前面和
 //  当前的一个数。假如前面可以给出最优的结构,那么这样加上当前
 //  点就可以了基于这样的想法,我们有可以从左开始考察,对于第一
 //  个数,他的最长个数应该为1,那么依次考察下面的元素,在前面是
 //  最优的情况下,后面的一个元素也可以达到最优。
 //  递归关系:
 //    max[i] = MAX(max[j] + 1)
 //               1<=j<=i
 //       Source[j] <= Source[i]
 //  
 //  如下面的例子:        1  3   7   4   8   2   9   0   4
 //  
 //  其得到的Max值的结果为:1  2   3   3   4   2   5   1   3
 //  如8这个元素,就有 1 3 4 8 这样的一个数列
 ///////////////////////////////////////////////////////////////////
 
 Max = (int*)malloc(sizeof(int) * length);
 //若Max不予比较都是1个长度
 for(i=0; i < length; i++)
  Max[i] = 1;
 //对所有元素从左到右逐步得到最优解
 for (i=0; i < length; i++)
 { 
  //当前i被选中,计算到i为止的最长个数
  for (j=0; j<i; j++)
   if (Source[i]>Source[j])
   {
    if (client < Max[j])
     client = Max[j];
   }
  Max[i] += client;/* 获得最优解 */
  client = 0;
 }
 ///////////////////////////////////////////////////////////////////
 //  在Max数组得到的基础上,可以知道只是个数,不是实际的数列,通过个
 //  数可以知道,先扫描得到最大的一个数,那么一定是包含这个数的数列
 //  是最大的,然后再向左找次大的,这样就可以从右到左(从大到小)找
 //  找到最大的数列,然后用一个数值,将其从小到大输出。
 ///////////////////////////////////////////////////////////////////
 printf("/n打印各元素假设在最长列中时的个数:/n");
 for(i=0; i < length; i++)
  printf("%d/n", Max[i]);
 
 printf("/n有最长列如下:/n");
 client = 0;
 for(i=0; i < length; i++)
  if (Max[i] > client)
  {
   client = Max[i];
   j = i;
  }
 
 //用于对结果的方向调整
 lenTemp = client;
 temp = (int*)malloc(sizeof(int) * lenTemp);
 temp[client] = Source[j];
 //打印次小的循环
 while(client > 1)
 {  
  --client;
  for(i=0; i < j; i++)
  {
   if (Max[i] == client && Max[j] >= Max[i])
    {
    temp[client] = Source[i];
    nextj = i;
   }
  }
  j = nextj;
 }
 for(i=1; i <= lenTemp; i++)
 {
  printf("%d ", temp[i]);
 }
 
 printf("/n");
}


///////////////////////////////////////////////////////////////////////
//
// 函数名       : CreatList
// 功能描述     : 输入序列
// 参数         : int Source[100]
// 返回值       : void
//
///////////////////////////////////////////////////////////////////////
int CreatList(int Source[100])
{
 int  i, j;

 printf("请输入序列,并以-1 结束输入:/n");
 for(i=0; i < 100; i++)
 { 
  scanf("%d", &j);
  if (j == -1)
   break;
  else
   Source[i] = j; 
 }
 return i;
}

原创粉丝点击