zoukankan      html  css  js  c++  java
  • LightOJ 1013 Love Calculator 【DP(LCS变形)】

    题目链接

    题意

    给两个字符串,求长度最短的字符串的长度以及个数,使得给出的两个串都是这个串的子串。

    分析

    LCS的变形,首先长度自然是len(s1)+len(s2)-len(LCS)。关键是有多少个这样的字符串。现在知道有两种DP的方法。

    题意

    给两个字符串,求长度最短的字符串的长度以及个数,使得给出的两个串都是这个串的子串。

    分析

    LCS的变形,首先长度自然是len(s1)+len(s2)-len(LCS)。关键是有多少个这样的字符串。现在知道有两种DP的方法。

    方法一(三维DP)

    设状态:
    dp[i][j][k]s1js2ki

    那么转移方程:
    考虑当前这个状态是由上一个状态加一个字母而来,那么转移时考虑这个字母是不是LCS中的字母

    dp[i][j][k]={dp[i1][j1][k1](s1[i]=s2[j])dp[i1][j][k1]+dp[i1][j1][k](s1[i]s2[j])

    注意初始化要把所有dp[i][i][0]和dp[i][0][i]初始化为0

    (也可以递推来写,不过初始化不一样,见下面代码)

    方法二(二维DP)

    看到这种方法在求LCS的时候就把个数求了出来,暂时没弄懂,思考过后再来补充一波
    设状态:
    dp[i][j]s1is2jLCS
    cnt[i][j]s1is2j
    转移方程:
    LCS按常规方法求

    cnt[i][j]=cnt[i1][j1](s1[i]=s2[j]))cnt[i1][j](s1[i]s2[j] and dp[i1][j]>dp[i][j1])cnt[i][j1](s1[i]s2[j] and dp[i1][j]<dp[i][j1])cnt[i][j1]+cnt[i1][j](s1[i]s2[j] and dp[i1][j]=dp[i][j1])

    AC代码

    姿势1

    //LightOJ 1013 Love Calculator
    //AC 2016-8-9 16:12:26
    //DP
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <cctype>
    #include <cstdlib>
    #include <cstring>
    #include <vector>
    #include <set>
    #include <string>
    #include <map>
    #include <queue>
    #include <deque>
    #include <list>
    #include <sstream>
    #include <stack>
    using namespace std;
    
    #define cls(x) memset(x,0,sizeof x)
    #define inf(x) memset(x,0x3f,sizeof x)
    #define neg(x) memset(x,-1,sizeof x)
    #define ninf(x) memset(x,0xc0,sizeof x)
    #define st0(x) memset(x,false,sizeof x)
    #define st1(x) memset(x,true,sizeof x)
    #define INF 0x3f3f3f3f
    #define lowbit(x) x&(-x)
    #define input(x) scanf("%d",&(x))
    #define bug cout<<"here"<<endl;
    //#define debug
    
    int T;
    char s1[100],s2[100];
    long long dp[100][100][100];
    
    int main()
    {
        #ifdef debug
            freopen("E:\Documents\code\input.txt","r",stdin);
            freopen("E:\Documents\code\output.txt","w",stdout);
        #endif
        input(T);
        for(int kase=1;kase<=T;++kase)
        {
            scanf("%s %s",s1+1,s2+1);
            int len1=strlen(s1+1),len2=strlen(s2+1);
            cls(dp);
            for(int i=0;i<=max(len1,len2);++i)
                dp[i][i][0]=dp[i][0][i]=1;
            for(int i=1;i<=len1+len2;++i)
            {
                for(int j=1;j<=len1;++j)
                {
                    for(int k=1;k<=len2;++k)
                    {
                        if(s1[j]==s2[k]) dp[i][j][k]=dp[i-1][j-1][k-1];
                        else dp[i][j][k]=dp[i-1][j][k-1]+dp[i-1][j-1][k];
                    }
                }
            }
            int res=max(len1,len2);
            for(;res<=len1+len2;++res)
                if(dp[res][len1][len2]) break;
            printf("Case %d: %d %lld
    ",kase,res,dp[res][len1][len2]);
        }
        return 0;
    }

    姿势2

    //LightOJ 1013 Love Calculator
    //AC 2016-8-9 16:25:35
    //DP
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <cctype>
    #include <cstdlib>
    #include <cstring>
    #include <vector>
    #include <set>
    #include <string>
    #include <map>
    #include <queue>
    #include <deque>
    #include <list>
    #include <sstream>
    #include <stack>
    using namespace std;
    
    #define cls(x) memset(x,0,sizeof x)
    #define inf(x) memset(x,0x3f,sizeof x)
    #define neg(x) memset(x,-1,sizeof x)
    #define ninf(x) memset(x,0xc0,sizeof x)
    #define st0(x) memset(x,false,sizeof x)
    #define st1(x) memset(x,true,sizeof x)
    #define INF 0x3f3f3f3f
    #define lowbit(x) x&(-x)
    #define input(x) scanf("%d",&(x))
    #define bug cout<<"here"<<endl;
    //#define debug
    
    int T;
    char s1[50],s2[50];
    int dp[50][50];
    long long cnt[100][50][50];
    
    int main()
    {
        #ifdef debug
            freopen("E:\Documents\code\input.txt","r",stdin);
            freopen("E:\Documents\code\output.txt","w",stdout);
        #endif
        input(T);
        for(int kase=1;kase<=T;++kase)
        {
            scanf("%s",s1+1);scanf("%s",s2+1);
            int len1=strlen(s1+1),len2=strlen(s2+1);
            cls(dp);
            for(int i=1;i<=len1;++i)
            {
                for(int j=1;j<=len2;++j)
                {
                    if(s1[i]==s2[j])
                        dp[i][j]=dp[i-1][j-1]+1;
                    else
                        dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
                }
            }
            cls(cnt);
            int len=len1+len2-dp[len1][len2];
            cnt[0][0][0]=1;
            for(int i=0;i<=len;++i)
            {
                for(int j=0;j<=len1;++j)
                {
                    for(int k=0;k<=len2;++k)
                    {
                        if(s1[j+1]==s2[k+1])
                            cnt[i+1][j+1][k+1]+=cnt[i][j][k];
                        else
                        {
                            cnt[i+1][j+1][k]+=cnt[i][j][k];
                            cnt[i+1][j][k+1]+=cnt[i][j][k];
                        }
                    }
                }
            }
            printf("Case %d: %d %lld
    ",kase,len,cnt[len][len1][len2]);
        }
        return 0;
    }

    姿势3

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <cctype>
    #include <cstdlib>
    #include <cstring>
    #include <vector>
    #include <set>
    #include <string>
    #include <map>
    #include <queue>
    #include <deque>
    #include <list>
    #include <sstream>
    #include <stack>
    using namespace std;
    
    #define cls(x) memset(x,0,sizeof x)
    #define inf(x) memset(x,0x3f,sizeof x)
    #define neg(x) memset(x,-1,sizeof x)
    #define ninf(x) memset(x,0xc0,sizeof x)
    #define st0(x) memset(x,false,sizeof x)
    #define st1(x) memset(x,true,sizeof x)
    #define INF 0x3f3f3f3f
    #define lowbit(x) x&(-x)
    #define input(x) scanf("%d",&(x))
    #define bug cout<<"here"<<endl;
    //#define debug
    
    int T;
    char s1[40],s2[40];
    int dp[40][40];
    long long cnt[40][40];
    
    long long fact[40];
    
    int main()
    {
        #ifdef debug
            freopen("E:\Documents\code\input.txt","r",stdin);
            freopen("E:\Documents\code\output.txt","w",stdout);
        #endif
        input(T);
        for(int kase=1;kase<=T;++kase)
        {
            scanf("%s %s",s1+1,s2+1);
            cls(dp);cls(cnt);
            int len1=strlen(s1+1),len2=strlen(s2+1);
            for(int i=0;i<=len1;++i)
                cnt[i][0]=1;
            for(int i=0;i<=len2;++i)
                cnt[0][i]=1;
            for(int i=1;i<=len1;++i)
            {
                for(int j=1;j<=len2;++j)
                {
                    if(s1[i]==s2[j])
                    {
                        dp[i][j]=dp[i-1][j-1]+1;
                        cnt[i][j]+=cnt[i-1][j-1];
                    }
                    else
                    {
                        if(dp[i-1][j]>dp[i][j-1])
                        {
                            dp[i][j]=dp[i-1][j];
                            cnt[i][j]=cnt[i-1][j];
                        }
                        else if(dp[i-1][j]<dp[i][j-1])
                        {
                            dp[i][j]=dp[i][j-1];
                            cnt[i][j]=cnt[i][j-1];
                        }
                        else
                        {
                            dp[i][j]=dp[i][j-1];
                            cnt[i][j]=cnt[i][j-1]+cnt[i-1][j];
                        }
                    }
                }
            }
            for(int i=0;i<=len1;++i)
            {
                for(int j=0;j<=len2;++j)
                    cout<<cnt[i][j]<<" ";
                cout<<endl;
            }
            printf("Case %d: %d ",kase,len1+len2-dp[len1][len2]);
            cout<<cnt[len1][len2]<<endl;
        }
        return 0;
    }
  • 相关阅读:
    Atitit fms Strait (海峡) lst 数据列表目录1. 4大洋 12. 著名的海大约40个,总共约55个海 13. 海区列表 23.1. 、波利尼西亚(Polynesia,
    Atitit trave islands list 旅游资源列表岛屿目录1. 东南亚著名的旅游岛屿 21.1. Cjkv 日韩 冲绳 琉球 济州岛 北海道 21.2. 中国 涠洲岛 南澳
    Atitit Major island groups and archipelagos 主要的岛群和群岛目录资料目录1. 岛群 波利尼西亚(Polynesia, 美拉尼西亚(Melanesia,
    Atitit glb 3tie city lst 三线城市列表 数据目录1. 全球范围内约90个城市 三线 12. 世界性三线城市全球共
    Atitit glb 1tie 2tie city lst 一二线城市列表数据约50个一线城市Alpha ++ 阿尔法++,,London 伦敦,,New York 纽约,,Alpha +
    Attit 现代编程语言重要特性目录第一章 类型系统 基本三大类型 2第一节 字符串 数字 bool 2第二节 推断局部变量 2第三节 动态类型 2第二章 可读性与开发效率 简单性 2
    Atitit 未来数据库新特性展望目录1. 统一的翻页 21.1. 2 Easy Top-N
    使用Chrome DevTools(console ande elements panel)进行xpath/css/js定位
    chrome -console妙用之定位xpath/js/css
    表达式树之构建Lambda表达式
  • 原文地址:https://www.cnblogs.com/DrCarlluo/p/6580592.html
Copyright © 2011-2022 走看看