最长公共子序列问题(动态规划)

Q:给定两个字符串s1和s2,求两个字符串的最长公共子序列
(例如:s1为abcfbc,s2为abfcab,则最长公共子序列为abcb或abfc,最长公共子序列可以不连续)
在这里插入图片描述

  • 首先将s1作为行,s2作为列,构建一个二维数组dp,dp[i][j]代表s1字符串中从0到i与s2字符串中从0到j的公共子序列
  • 如果s1[0]==s2[0],则dp[0][0]=1,否则dp[0][0]=0
  • 由上图我们可以观察到dp[i][0]是dp[i-1][0]与dp[i][0]的最大值,dp[0][j]是dp[0][j-1]与dp[0][j]的最大值,据此我们可以先将二维数组的第一行和第一列进行初始化
  • 之后我们可以看到如果s1[i]==s2[j],那么dp[i][j]就是当前格子左斜上方的值加一,就是dp[i-1][j-1]+1;如果不相等,那么dp[i][j]就是dp[i-1][j]与dp[i][j-1]的最大值;由此我们将二维数组全部初始化
  • 我们找到最后一行最后一列的格子,如果它的值和它上方或者左方的格子值相同,那么就证明没有增加公共子序列长度,在这里我们优先走它的上方格子;如果它和它左边,上边的格子值都不相同,那么证明增加了公共子子序列长度,它走到它的左上斜方格子;依次向上寻找路径,最后得到最长公共字串
#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
using namespace std;
int main()
{
   string s1;
   string s2;
   while(cin>>s1>>s2)
   {
      int len1=s1.size();
      int len2=s2.size();
      vector<vector<int>> dp(len1,vector<int>(len2,0));
      if(s1[0]==s2[0])
         dp[0][0]=1;
      else 
         dp[0][0]=0;
      for(int i=1;i<len1;++i)             //初始化第一列
      {
         if(s1[i]==s2[0])
            dp[i][0]=1;
         else
            dp[i][0]=0;
        dp[i][0]=max(dp[i][0],dp[i-1][0]);
      }
      for(int j=1;j<len2;++j)                     //初始化第一行
      {
         if(s2[j]==s1[0])
           dp[0][j]=1;
        else
           dp[0][j]=0;
        dp[0][j]=max(dp[0][j],dp[0][j-1]);
      }
      for(int i=1;i<len1;++i)
      {
         for(int j=1;j<len2;++j)
         {
            dp[i][j]=max(dp[i][j-1],dp[i-1][j]);
            if(s1[i]==s2[j])
               dp[i][j]=max(dp[i][j],dp[i-1][j-1]+1);
         }
      }
      cout<<dp[len1-1][len2-1]<<endl;
  }
          
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值