算法之道_最长公共子序列_序列可间隔但顺序固定

本文详细阐述了使用C语言实现字符串匹配的方法,包括动态规划算法的应用。通过实例代码展示了如何在字符数组中查找子串,并利用动态规划优化搜索效率。

#include<stdio.h>
#include<string>
int Max(int x, int y)
{
 return x>y?x:y;
}
int  find(const char *A,const char*B)
{
 int i = 0;
 int j = 0;
 int Record[20][20] = {0};
 int LenA = strlen(A);
 int LenB = strlen(B);
 int flag = 0;
 for( j = 0; j < LenB; j++ )
 {
  if(A[0]==B[j]||flag==1)
  {
   Record[0][j]=1;
   flag=1;
  }
 }
 flag = 0;
 for(i=1;i <LenA; i++)
 {
  if(B[0]==A[i]||flag==1)
  {
   Record[i][0] = 1;
   flag = 1;
  }
 }
 
 for ( i = 1; i < LenA; i++ )
  for( j = 1; j < LenB; j++ )
  {
   if(B[j]==A[i])
    Record[i][j] = Record[i-1][j-1] + 1;
   else 
   {
    Record[i][j] = Max(Record[i-1][j],Record[i][j-1]);
   }
   
  }
  
  printf("%d\n",Record[LenA-1][LenB-1]);
  return 0;
}

void main()
{
 char A[20]={"INTHEBEGINING"};
 char B[20]={"ALLTHINGSARELOST"};
    int num = find(A,B);
}

算法思想:若当前A数组元素与B数组元素相同,则此时最大子序列为当前A,B各减 一元素时的最大子序列.若当前A,B元素不同,则取A减去一个元素与B的当前元素,以及B减去一个元素与A的当前元素中的大者。

<think>嗯,用户问的是子序列的定义和示例。首先,我需要先回忆一下相关的知识。子序列在字符串和序列处理中很常见,比如最长公共子序列或者最长递增子序列这些算法问题。根据用户提供的引用内容,引用[2]里提到子序列的定义是:给定一个序列X,另一个序列Z,如果存在严格递增的X的下标序列,使得Z中的每个元素对应X中的位置,那么Z就是X的子序列。比如,X=<A,B,C,D>,Z=<A,C,D>就是一个子序列,对应的下标是1,3,4。 然后引用[3]中的例子是关于最长递增子序列的,比如序列X=[10,22,9,33,…],最长递增子序列是[10,22,33,50,60,80]。这说明子序列不需要连续,但必须保持原有顺序,并且元素递增。这里要注意子序列的两个关键点:元素顺序必须保持原序列中的相对位置,但不要求连续;元素是否递增取决于具体问题,但子序列本身不一定是递增的,只有在特定问题如LIS中才需要递增。 再看引用[4],里面提到了最长公共子序列的动态规划解法,其中递推公式分为两种情况:当前字符相同或不同。这进一步说明子序列的匹配需要顺序一致,但可以间隔其他字符。 用户可能是在学习动态规划相关的问题时遇到了子序列的概念,所以需要明确子序列的基本定义和示例,可能为后续学习最长公共子序列或最长递增子序列打基础。需要确保回答中明确子序列的两个主要特征:顺序保持和不需要连续。同时,给出不同例子,比如字符串和数字序列的例子,帮助用户理解。另外,需要区分子序列和子串的不同,子串是连续的,而子序列不是。 用户可能存在的疑惑点在于子序列和子串的区别,以及如何应用子序列的概念到实际问题中,比如动态规划解法。因此,在回答时应该明确这些点,并引用提供的参考资料中的例子,比如引用[2]和引用[3]中的例子,来增强可信度。同时,生成的相关问题需要围绕子序列的应用和解决方法展开,比如动态规划的具体步骤、如何计算最长公共子序列等。</think>### 子序列的定义及概念 #### 定义 子序列(Subsequence)指从原序列中**按顺序**选取若干元素组成的序列,这些元素**不需要连续**,但必须保持其在原序列中的相对顺序。数学形式化定义为: > 给定序列 $X = \langle x_1, x_2, \dots, x_m \rangle$,若存在严格递增的下标序列 $\langle i_1, i_2, \dots, i_k \rangle$($1 \leq i_1 < i_2 < \dots < i_k \leq m$),使得 $Z = \langle x_{i_1}, x_{i_2}, \dots, x_{i_k} \rangle$,则称 $Z$ 是 $X$ 的子序列[^2]。 #### 关键特性 1. **顺序保留**:子序列元素必须与原序列顺序一致。 2. **非连续性**:允许跳过中间元素。 3. **长度灵活**:子序列长度可为 $0$(空序列)到原序列长度。 #### 示例 1. **字符串示例** - 原序列:$X = \text{"ABCD"}$ - 有效子序列:$\text{"ACD"}$(对应下标 $1,3,4$) - 无效子序列:$\text{"ADB"}$(顺序破坏) 2. **数值序列示例** - 原序列:$X = [10, 22, 9, 33, 21, 50]$ - 有效子序列:$[10, 22, 33, 50]$(严格递增) - 无效子序列:$[22, 10]$(顺序破坏) #### 与子串(Substring)的区别 | 特性 | 子序列 | 子串 | |------------|----------------------------|--------------------| | 连续性 | 不要求连续 | 必须连续 | | 应用场景 | 动态规划问题(如LCS、LIS) | 字符串匹配 | #### 应用场景 子序列概念广泛用于: 1. **最长公共子序列(LCS)**:比较两个序列的相似性[^1][^4]。 2. **最长递增子序列(LIS)**:寻找序列中的最长递增部分[^3]。 3. **生物信息学**:DNA序列比对。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值