• 最长公共子窜和最长公共子序列(LCS)


    他们都是用dp做;复杂度都是O(N方)

    有一个大佬的博客写的很详细,是关于最长公共子序列的:https://blog.csdn.net/hrn1216/article/details/51534607#comments;

    我觉得一开始处理这种问题比较棘手,无从下手,而dp一般有两种状态转移的思考方式,一种是正着,一种是倒着,而且dp一般记录的信息都是按照一定顺序,以什么结尾的答案,或者以什么开头的答案具有的一种性质,然后我们按顺序增加或减少开头或者结尾,形成一种状态的传递关系,还有一些状态的传递可能是像dfs中有某一状态走到一部走到另一状态,还是按顺序,由小规模到大规模;假设两个字符串长度为len1,和len2,那么我们要知道他们的公共子序列,就要知道小一些规模的同一个问题,这里我们通过缩短长度来缩小规模;

    这里可以分两种情况,s1[len1]=s2[len2],那么它的答案dp[len1][len2]=dp[len1-1][len2-1]+1;

    如果s1[len1]!=s2[len2], s1[len1],s2[jlen2],最多有一个是有效信息存在答案里面和另一个窜前面的元素配对,所以 dp[len1][len2]=max(dp[len1-1][len2],dp[len1][len2-1]);这样就缩小了规模,我们按照这种方法推广出去;

     

    我们dp[i][j]代表s1 窜前i个字母和s2窜 前 j 个字母最长公共子序列,如果s1[i]=s2[j] ,dp[i][j]=d[i-1][j-1]+1,如果s1[i]!=s2[j], s1[i],s2[j],最多有一个是有效信息就是可能存在答案里面,和前面的配对,所以 dp[i][j]=max(dp[i-1][j],dp[i][j-1]);

    大致代码如下:(记得初始化)

     1 #include<iostream>
     2 using namespace std;
     3 char a1[1001],a2[1001],dp[1001][1001]={0};
     4 int main()
     5 {
     6     int n1,n2;
     7     cin>>n1>>n2;
     8     for(int i=1;i<=n1;i++)
     9         cin>>a1[i];
    10     for(int j=1;j<=n2;j++)
    11         cin>>a2[j];
    12     for(int i=1;i<=n1;i++)
    13         for(int j=1;j<=n2;j++)
    14             if(a1[i]==a2[j])
    15                 dp[i][j]=dp[i-1][j-1]+1;
    16             else
    17                 dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
    18     cout<<dp[n1][n2]; 
    19 }
  • 相关阅读:
    RTC驱动程序分析
    Linux下的RTC子系统
    [置顶] 谈EXPORT_SYMBOL使用
    《Linux内核修炼之道》精华分享与讨论(5)——Kernel地图:Kconfig与Makefile
    写出高效优美的单片机C语言代码
    哈夫曼树
    如何提高浮点数变整数的精度
    CF798C Mike and gcd problem
    CF822C Hacker, pack your bags!
    CF821C Okabe and Boxes
  • 原文地址:https://www.cnblogs.com/hjw201983290498/p/12726870.html
Copyright © 2020-2023  润新知