C语言求最长公共子序列

基础算法 专栏收录该内容
19 篇文章 0 订阅

下面是一段自写代码的呈现,如果后期有不明白,自己查阅收藏博客
主要方法:画出表格图,列出递归公式
di

自写1:
#include<stdio.h>
#include<string.h>
void print(int i, int j, int s, char x[], char y[]);
int c[200][200];   //用c[i][j]记录X[i]与Y[j] 的LCS 的长度
int b[200][200];   //b[i][j]记录c[i][j]是通过哪一个子问题的值求得的,以决定搜索的方向
char f[200];
/*-----------------------分割线--------------------------------*/
/*取c[i-1][j]和c[i][j-1]的最大值,并记录c[i][j]是通过哪一个子问题的值求得的,以决定搜索的方向*/
int Max(int m, int n, int i, int j)//m=c[i-1][j],n=c[i][j-1]
{
 if (m > n)
  //请输入字符串X:ACDSXZBF
  //请输入字符串Y:ACGHNBFZ
 {
  b[i][j] = -1;
  return m;//返回大的c[i-1][j] 
 }
 else
 {
  b[i][j] = 1;
  return n;//如果c[i-1][j]<=c[i][j-1],返回c[i][j-1] 
 }
}
/*-----------------------分割线--------------------------------*/
int LCS(char x[], char y[])
{
 int i, j;
 int x_len, y_len;
 x_len = strlen(x);
 y_len = strlen(y);
 for (i = 0; i < x_len+1; i++)//发现一个奇怪的问题这边第一排第一列不初始化居然也行
  c[i][0] = 0;
 for (j = 0; j < y_len + 1; j++)
  c[0][j] = 0;
 for (i = 1; i <= x_len; i++)
 {
  for (j = 1; j <= y_len; j++)
  {
   if (x[i - 1] == y[j - 1])
   {
    c[i][j] = c[i - 1][j - 1] + 1;
    b[i][j] = 0;//画龙点睛之笔 
   }
   else
   {
    c[i][j] = Max(c[i - 1][j], c[i][j - 1], i, j);
   }
  }
 }
 /*-------------------------分割线---------------------------------------*/
 //打印X和Y的LCS
 printf("X和Y的LCS是:");
 print(x_len, y_len, c[x_len][y_len], x, y);
 printf("%s", f);
 printf("\n");
 return c[x_len][y_len];
}
/*-----------------------分割线--------------------------------*/
/*递归打印LCS的元素内容*/
void print(int i, int j, int s, char x[], char y[])   //i.j两个字符串的长度,s公共子序列的长度,两个字符串 .这边就是根据后面倒推出公共子序列的。******
{
 if (b[i][j] == 0)//这个地方是有有问题的 ,后续代码解决了这个问题 
 {
  f[s - 1] = x[i - 1];
  i--; j--; s--;//因为下一个递归的数就是b[i-1][j-1],公共子序列地长度也就跟着递归减1
  print(i, j, s, x, y);
 }
 else if (b[i][j] == -1)
 {
  i--; //m = c[i - 1][j], n = c[i][j - 1],大于返回-1
  print(i, j, s, x, y);
 }
 else if (b[i][j] == 1)
 {
  j--;
  print(i, j, s, x, y);
 }
}
/*------------------------------分割线----------------------------------------*/
void main()
{
 char X[200], Y[200];
 int i, j, s;
 printf("请输入字符串X:");
 scanf("%s", X);
 while (strlen(X) > 200)
 {
  printf("您输入的字符串超过最大长度,请重新输入!");
  scanf("%s", X);
 }
 printf("请输入字符串Y:");
 scanf("%s", Y);
 while (strlen(Y) > 200)
 {
  printf("您输入的字符串超过最大长度,请重新输入!");
  scanf("%s", Y);
 }
 s = LCS(X, Y);
 printf("X和Y的LCS: %d \n", s);
}

自写2:
//最大公共子序列的问题
#include<stdio.h>
#include<string.h>
#define MAXSIZE 200
int c[200][200];
int b[200][200];
char f[200];
void print(int i,int j,int s,char x[],char y[]);
int max(int m,int n,int i,int j)//c[i][j-1].c[i-1][j]
{
 if(m>n)
 {
 b[i][j]=1;
 return m;}
 else
 {
 b[i][j]=-1;
 return n;}
}
int LCS(char x[],char y[])
{
 int i,j;
 int m,n;
 m=strlen(x);
 n=strlen(y);
 for(i=0;i<m+1;i++)
 c[i][0]=0;
 for(j=0;j<n+1;j++)
 c[0][j]=0;
 for(i=1;i<=m;i++)
 {
  for(j=1;j<=n;j++)
  {
   if(x[i-1]==y[j-1])
   {
   b[i][j]=0;
   c[i][j]=c[i-1][j-1]+1;
   }
   else
   {
    c[i][j]=max(c[i][j-1],c[i-1][j],i,j);
   }
  }
 }
 printf("X和Y的LCS是:");
 print(m,n,c[m][n],x,y);
 printf("%s\n",f);
 return c[i-1][j-1];
}
void print(int i,int j,int s,char x[],char y[])
{
 if(b[i][j]==0)
 {
  f[s-1]=x[i-1];
  i--;j--;s--;
  print(i,j,s,x,y);
 }
 else if(b[i][j]==1)
 {
  j--;
  print(i,j,s,x,y);
 }
 else if(b[i][j]==1)
 {
  i--;
  print(i,j,s,x,y);
 }
}
int main()
{
 char x[MAXSIZE];char y[MAXSIZE];
 printf("你要输入的X字符串为:");
 scanf("%s",x);
 printf("你要输入的Y字符串为:");
 scanf("%s",y);
 int s=LCS(x,y);
 printf("公共子序列长度为:%d\n",s);
 return 0;
}
  • 2
    点赞
  • 0
    评论
  • 5
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值