动态规划解最长子序列

来源:互联网 发布:淘宝怎么优化排名 编辑:程序博客网 时间:2024/06/11 09:28
/////////////动态规划解最长子序列/////////////////////
动态规划:对大问题进行小问题分解
 情况1:当前元素在比对序列存在相同元素,子序列增加,比对序列减少
 情况2:当前元素在比对序列不存在相同元素,子序列不变,比对序列不变
 
使用结构体:
 SaveLcs (bool LCSExist; int length;) //保存lcs存在与否的信息
 
函数说明:LCS (char str1[],char str2[],SaveLcs sl[MAX][MAX])
 输入:char str1[],char str2[] //用于比对的两个字符串
    saveLcs sl[MAX][MAX]     //用于保存匹配信息的二维表
 输出:返回公共子序列长度
  返回 saveLcs 二维表
 
算法简析:
 初始化第一列
 for (each char from str1)  //将str1作为列循环
  for (each char from str2)   //将str2作为行循环
   if str1 == str2   //判断当前遍历的str1,str2,节点字符是否相同
    判断是否已经记录,否着修改      
//////////////////////////////////////////////////////

#include <stdio.h>
#include <string.h>
#define MAX 10
typedef struct
{
 bool LCSExist; //是否存在lcs
 int length;  //lcs长度
}SaveLcs;
void print(SaveLcs sl[MAX][MAX],int len1,int len2);

int LCS (char str1[],char str2[],int rec[],SaveLcs sl[MAX][MAX]);

int main ()
{
 char str1[MAX] = {'a', 'A', 'A', 'B', 'c', 'd', 'F', 'g'};
 char str2[MAX] = {'A', '1', 'A', '2', '3', 'B', 'F'};
 SaveLcs sl[MAX][MAX];
 int rec[MAX]; //记录str2中共同元素的位置
 int n,i;
 
  printf ("计算LCS(%s,%s)\n",str1,str2);
 n = LCS (str1,str2,rec,sl);
 printf ("构建的表(是否有共同序列,长度)\n");
 print (sl,strlen(str1),strlen(str2));  
 printf ("LCS(%s,%s)=<",str1,str2); 
 for (i=0; i<n; i++)
 {
  printf ("%c",str2[rec[i]]);
  if (i!=n-1)
   printf (",");
  else
   printf (">\n");
 } 
 return 0;
}
void print(SaveLcs sl[MAX][MAX],int len1,int len2)
{
 int i,j;
 for (i=0; i<len2; i++) //行
 {
  for (j=0; j<len1; j++)//列
  {
   printf ("(%d,%d) ",sl[i][j].LCSExist,sl[i][j].length);
  }
  printf ("\n");
 }
}
int LCS (char str1[],char str2[],int rec[],SaveLcs sl[MAX][MAX])
{
 int i,j,k;
 bool line[MAX] = {false};
 int n = 0;
 if (str2[0] == str1[0])
 {
  for (j=0; j<strlen(str2); j++)
  {
   sl[j][0].LCSExist = true;
   sl[j][0].length = 1;
  }   
 }
 else
 {
  for (j=0; j<strlen(str2); j++)
  {
   sl[j][0].LCSExist = false;
   sl[j][0].length = 0;
  }   
 } 
 for (i=1; i<strlen(str1); i++)//列
 {
  for (j=0; j<strlen(str2); j++)//行
  {
   if (j==0)
    sl[j][i] = sl[j][i-1];
   else
   {
    if (sl[j-1][i].length > sl[j][i-1].length)
     sl[j][i] = sl[j-1][i];
    else 
     sl[j][i] = sl[j][i-1]; 
   } 
   if (str1[i] == str2[j])
   {
    sl[j][i].LCSExist = true;
    for (k=0; k<n; k++)
     if (str2[j] == str2[rec[k]]) break;
    if (k==n || (j!=rec[k]&&!line[i])) //公共序列没有,
    {
     sl[j][i].length ++;
     rec[n] = j;
     n++;
     line[i] = true;
    }    
   }   
  }
 }
 return n;
}
原创粉丝点击