• LightOJ1157 LCS Revisited(DP)


    题目求两个字符串s1,s2不同的LCS个数。

    经典的求LCS的DP是这样的:

    • LCS[i][j]表示s1[0...i]和s2[0...j]的LCS
    • LCS[i][j]从LCS[i-1][j-1]+1(s1[i]==s2[j])或max(LCS[i-1][j],LCS[i][j-1])(s1[i]!=s2[j])转移来

    计数的话也跟着转移,用dp[i][j]计数。不过搞不出。。看了别人的解法才恍然大悟,要减去多算的部分,即s1[i]!=s2[j]且LCS[i-1][j]等于LCS[i][j-1]时这种情况的转移,如果只是dp[i][j]=dp[i-1][j]+dp[i][j-1]可能会有重复算的部分:

    • LCS[i-1][j]等于LCS[i][j-1],且LCS[i-1][j-1]不与它们相等,那样s1[0...i-1]和s2[0...j]所有的LCS必定以s2[j]为结尾,s1[0...i]和s2[0...j-1]同理,所以s1[0...i-1]和s2[0...j]所有的LCS和s1[0...i]和s2[0...j-1]的所有LCS没有相交部分,dp[i][j]=dp[i-1][j]+dp[i][j-1];
    • 而如果LCS[i-1][j-1]等于它们的情况,就说明存在不以s1[i]和s2[j]结尾的LCS,多算了一次s1[0...i-1]和s2[0...j-1]的所有LCS的部分,这时dp[i][j]=dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1]。

    另外注意负数取模。

     1 #include<cstdio>
     2 #include<cstring>
     3 using namespace std;
     4 int lcs[1111][1111],d[1111][1111];
     5 int main(){
     6     char s1[1111],s2[1111];
     7     int t;
     8     scanf("%d",&t);
     9     for(int cse=1; cse<=t; ++cse){
    10         scanf("%s%s",s1+1,s2+1);
    11         int l1=strlen(s1+1),l2=strlen(s2+1);
    12         for(int i=0; i<=l1; ++i) d[i][0]=1;
    13         for(int i=0; i<=l2; ++i) d[0][i]=1;
    14         for(int i=1; i<=l1; ++i){
    15             for(int j=1; j<=l2; ++j){
    16                 if(s1[i]==s2[j]){
    17                     lcs[i][j]=lcs[i-1][j-1]+1;
    18                     d[i][j]=d[i-1][j-1];
    19                 }else if(lcs[i-1][j]==lcs[i][j-1]){
    20                     lcs[i][j]=lcs[i-1][j];
    21                     d[i][j]=(d[i-1][j]+d[i][j-1])%1000007;
    22                     if(lcs[i-1][j-1]==lcs[i-1][j]) d[i][j]=((d[i][j]-d[i-1][j-1])%1000007+1000007)%1000007;
    23                 }else if(lcs[i-1][j]>lcs[i][j-1]){
    24                     lcs[i][j]=lcs[i-1][j];
    25                     d[i][j]=d[i-1][j];
    26                 }else{
    27                     lcs[i][j]=lcs[i][j-1];
    28                     d[i][j]=d[i][j-1];
    29                 }
    30             }
    31         }
    32         printf("Case %d: %d
    ",cse,d[l1][l2]);
    33     }
    34     return 0;
    35 } 
  • 相关阅读:
    Python基础:条件判断与循环的两个要点
    oozie note
    Dynamics CRM2013 Server2012R2下IFD部署遇到There is already a listener on IP endpoint的解决方法
    监控系统的多协议直播(RTSP RTMP HTTP Live Streaming)
    易迅,生的霸气,死的窝囊
    js中的splice方法和slice方法简单总结
    JAVA虚拟机的安装以及JAVA的环境配置
    JS函数种类详解
    IDEA多线程调试设置
    Java中的HashMap源码记录以及并发环境的几个问题
  • 原文地址:https://www.cnblogs.com/WABoss/p/5248446.html
Copyright © 2020-2023  润新知