美文网首页动态规划
* 最长公共子序列

* 最长公共子序列

作者: 小幸运Q | 来源:发表于2018-07-10 19:27 被阅读9次

名词解释:

sadstoryadminsorry的最长公共子序列是adsory,长度为6。

dp的值代表在该(i,j)串中已匹配的个数。


走过来的路径:

对A与B两个字符串,取A[i],B[j]为例:

  1. 若A[i]==B[j]:

A[i]与B[j]可以组成一对新的公共子序列,所以dp[i][j]==dp[i-1][j-1]+1

  1. 若A[i]!=B[j]:

i或者j中至少有一个不能成为公共子序列的成员,因为i!=j,所以i必须跟j之前的配对,那么j就凉了,所以dp[i][j]==dp[i][j-1],或者dp[i][j]==dp[i-1][j],看谁更大(配对多)就选哪个。

但是如果出现相等的话怎么办?-->走两边都能得出正确的解

image.png

求过来的路径:

image.png

如果a[i],b[j]处字符相等,打印点,x--,y--

if(a[x-1]==b[y-1]){
  cout<<a[x-1]<<">>";
  x--;
  y--;
}

如果字符不相等,则选择dp大的一边走,如果dp[x-1][y]与dp[x][y-1]相等,则会有两种走法进而演化出多种不同的可能,如果考这个的话可以用DFS递归解。

else{
  if(dp[x-1][y]>dp[x][y-1]){
    x--;
  }
  else{
    y--;
  }
}

遍历所有可能子序列的解法:

void tracefullpath(int i,int j,vector<int>vv){
  if(i>=1&&j>=1){
    if(a[i-1]==b[j-1]){
      //cout<<"-->";
      vv.push_back(i-1);
      tracefullpath(i-1,j-1,vv);
    }
    else if(dp[i-1][j]==dp[i][j-1]){
        tracefullpath(i-1,j,vv);
        tracefullpath(i,j-1,vv);
    }
    else if(dp[i-1][j]>dp[i][j-1]){
      tracefullpath(i-1,j,vv);
    }
    else{
      tracefullpath(i,j-1,vv);
    }
  }
  else{
    print(vv);
    return;
  }
}

测试数据:

abcfbc abfcab
programming contest
abcd mnp

4
2
0

示例代码:

#include <bits/stdc++.h>
using namespace std;
#define N 1000
int points,edges;
char a[N];
char b[N];
// i是从1到n的,所以字符串匹配是a[i-1]而不是a[i]
// char数组从0开始,dp从1开始,要注意
int dp[N][N]={0};
// 根据原操作逆向出原路径。
void chase_path(int x,int y){
  cout<<"path: ";
  while(y>=1&&x>=1){
    if(a[x-1]==b[y-1]){
      cout<<a[x-1]<<">>";
      x--;
      y--;
    }
    else{
      if(dp[x-1][y]>dp[x][y-1]){
        x--;
      }
      else{
        y--;
      }
    }
  }
}
int main() {
  int i,j;
  scanf("%s %s",&a,&b);
  int len_a=strlen(a);
  int len_b=strlen(b);
  // 获取字符串长度

  for(i=1;i<len_a+1;i++){
    for(j=1;j<len_b+1;j++){
      if(a[i-1]==b[j-1]){
        // char数组从0开始,所以要a/b要-1
        dp[i][j]=dp[i-1][j-1]+1;
        // 在ij未放入的时候最优基础上+1
      }
      else{
        dp[i][j]=max(dp[i][j-1],dp[i-1][j]);
        // 如果i,j放了跟没放一样,那么就跟dp[i][j-1]/dp[i-1][j]一样了
      }
    }
  }
  cout<<"\nCommon Length:"<<dp[len_a][len_b];
  return 0;
}

相关文章

  • 公共子序列问题

    最长公共子序列 最长上升子序列 最长公共上升子序列

  • 最长公共子序列和最长公共子串

    最长公共子序列和最长公共子串区别 最长公共子串(Longest CommonSubstring)和最长公共子序列(...

  • 算法(04)动态规划

    零钱问题 背包问题 最长公共子序列 最长公共子串 最长上升子序列 最大连续子序列和

  • LCS问题

    LCS问题包括最长公共子序列和最长公共子串,其中,最长公共子串要求必须连续。 对于二者的求解方式 最长公共子序列:...

  • 子序列问题

    最长公共子序列 最长上升/下降/不升/不降子序列

  • 子串 子序列 总结

    最长公共子串 子串的要求比子序列严格,所以可以讨论子串的终点 最长公共子序列 DP解 递归+memo 最长公共回文...

  • 序列比对(二十四)——最长公共子序列

    原创:hxj7 本文介绍如何求解两个字符串的最长公共子序列。 最长公共子序列问题 前文《序列比对(23)最长公共子...

  • lintcode 最长公共子序列

    给出两个字符串,找到最长公共子序列(LCS),返回LCS的长度。说明最长公共子序列的定义: 最长公共子序列问题是在...

  • 字符串的几个问题

    1.最长公共子序列2.最长公共子串3.最长回文串4.最长回文序列5.最长递增序列6.最长先增后减序列7.(最短)编...

  • 算法问题清单

    最大子序列和最长公共子序列最长公共子串大整数相乘/除/加数组最大乘积

网友评论

    本文标题:* 最长公共子序列

    本文链接:https://www.haomeiwen.com/subject/bgafpftx.html