Robin's Log

那能得叙曲幽静,唯有念头笑巍峨

原创 最长公共子序列收藏

新一篇: 最大子序列和线性算法

/*若给定序列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;
}

发表于 @ 2005年03月24日 11:59:00|评论(loading...)|编辑

旧一篇: The shifting preoccupations of the 20th century and the early years of the 21st.

评论

#ZD 发表于2005-12-15 15:05:00  IP: 192.168.1.*
刚刚看到,原来作者是purdue University的牛人啊,敬仰敬仰
#hongwejin 发表于2005-12-26 22:13:00  IP: 202.107.208.*
好久没有来自己的blog了,楼上的我不是什么牛人,只是喜欢算法这个东西。
#hongwejin 发表于2005-12-26 22:15:00  IP: 202.107.208.*
purdue 的计算机系确实很牛,但是我没有在那边待很长时间,我只是purdue的交流生。
#guchwu 发表于2007-10-05 14:01:25  IP: 125.34.79.*
真失望!
完全文不对题。
代码求的是单个数列的最长递增子序列吧。
purdue的也靠忽悠?
#hongweijin 发表于2007-10-05 14:24:46  IP: 125.126.175.*
呵呵,楼上的严重了。首先,这个代码我是大一的时候写的,我是大四到了Purdue,因此没有关系。
再者,假如我写错了,您可以批评,但是没有必要做攻击。
另外,我在这里发表文章不是为了给您去阅读,因为真正的阅读者非常明白如何去剔除其中的错误。就比如你要是和莎士比亚纠缠其童年的作品,那我估计问题就只能出在您自己本人的身上。

最后,本人现在已经不涉及IT,只是保持“隔离”的状态。所以也不会去更新。

当然谢谢您的指点。
#fangxishanglu 发表于2007-10-09 20:36:06  IP: 121.32.14.*
楼主厉害,看来和你的差距还真是大啊
得加倍努力才行了 -_-#!!
谢谢分享
发表评论  


当前用户设置只有注册用户才能发表评论。如果你没有登录,请点击登录
Csdn Blog version 3.1a
Copyright © Robin Li