• tyvj2030 题解


     

    给出两个由数字和字母组成的非空字符串ST,求:

    1ST的最长公共子序列的长度。

    2ST的本质不同的非空公共子序列的个数。

    3ST的各种长度的本质不同的非空公共子序列的个数。

    思考过程:考场上,果断只会第一问,但是听完题解后,发现事实上他们的思想和第一问是一致的。(此题解借鉴讲题解人)

    首先考虑第二问,设dp(i,j)表示s串的前i位和t串的前j位,分两种情况讨论

    若s[i]=s[j],则直接把这个字符接在后面,有接和不接两种则dp(i,j)=dp(i-1,j-1)*2,但是我们需要将此结果减去dp(u-1,v-1)其中uv是ij最近相同字符, 考虑dp[u-1][v-1]对应集合中的串x,记S[i]=c,则x,xc∈dp[u][v],则x,xc∈dp[i-1][j-1]。串xc就会在dp[i][j]的集合中出现两遍。

    若是s[i]!=s[j],则dp(i,j)=dp(i,j-1)+dp(i-1,j)-dp(i-1,j-1)

    这样就解决了第二问,而第三问就是在第二问上加一维,k为长度,dp方程则是一模一样。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cstdlib>
     5 using namespace std;
     6 string a,b;
     7 int f[305][305];
     8 int g[305][305][305];
     9 int prea[305],preb[305];
    10 int ans;
    11 const int MOD=1048576;
    12 const int SIE = 0xFFFFF;
    13 int n,m;
    14 int ss;
    15 int main()
    16 {
    17 //    freopen("common5.in","r",stdin);
    18 //    freopen("common5.out","w",stdout);
    19     cin>>a;cin>>b;
    20     n=a.size();
    21     m=b.size();
    22     a='0'+a;
    23     b='0'+b;
    24     for(int i=1;i<=n;i++)
    25     {
    26         for(int j=1;j<=m;j++)
    27         {
    28             if(a[i]==b[j])f[i][j]=f[i-1][j-1]+1;
    29             f[i][j]=max(f[i][j],f[i-1][j]);
    30             f[i][j]=max(f[i][j],f[i][j-1]);
    31         }
    32     }
    33     printf("%d
    ",f[n][m]);
    34     ss=f[n][m];
    35     for(int i=1;i<=n;i++)
    36     {
    37         int j=i-1;
    38         while(j>0 && a[j]!=a[i])j--;
    39         prea[i]=j;
    40     //    cout<<j;
    41     }
    42     for(int i=1;i<=m;i++)
    43     {
    44         int j=i-1;
    45         while(j>0 && b[j]!=b[i])j--;
    46         preb[i]=j;
    47         //cout<<j;
    48     }
    49     for(int i=0;i<=n;i++)
    50     {
    51         for(int j=0;j<=m;j++)
    52         {
    53             g[i][j][0]=1;
    54         }
    55     }
    56     for(int i=1;i<=n;i++)
    57     {
    58         for(int j=1;j<=m;j++)
    59         {
    60             if(a[i]==b[j])
    61             {
    62                 for(int k=1;k<=ss;k++)
    63                 {
    64                     g[i][j][k]=(g[i-1][j-1][k]+g[i-1][j-1][k-1])&SIE;
    65                 }
    66                 if(prea[i] && preb[j])
    67                 {
    68                     for(int k=1;k<=ss;k++)
    69                     {
    70                         g[i][j][k]=(g[i][j][k]-g[prea[i]-1][preb[j]-1][k-1])&SIE;
    71                     }
    72                 }
    73             }
    74             else
    75             {
    76                 for(int k=1;k<=ss;k++)
    77                 {
    78                     g[i][j][k]=(g[i-1][j][k]+g[i][j-1][k]-g[i-1][j-1][k])&SIE;
    79                     //cout<<i<<" "<<j<<" "<<k<<" "<<g[i][j][k]<<endl;
    80                 }
    81             }
    82         }
    83     }
    84     int sum=0;
    85     for(int i=1;i<=ss;i++)sum=(sum+g[n][m][i])%MOD;
    86     printf("%d
    ",sum);
    87     for(int i=1;i<=ss;i++)printf("%d
    ",g[n][m][i]);
    88     return 0;
    89 }
    View Code
  • 相关阅读:
    310. Minimum Height Trees
    279. Perfect Squares
    675. Cut Off Trees for Golf Event
    210. Course Schedule II
    407. Trapping Rain Water II
    vue-element-admin中如何vuex的使用
    webpack相关---vue-element-admin
    公共vendor是什么---vue-element-admin
    项目mock 模拟数据---vue-element-admin
    vue+ssr signalR---vue-element-admin
  • 原文地址:https://www.cnblogs.com/sillygirl/p/3905623.html
Copyright © 2020-2023  润新知