• BZOJ 2423: [HAOI2010]最长公共子序列


    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2423

    题解:唔,我其实也不会,然后去看了题解。。。

    大概意思是我们不仅仅用f[i][j]来表示最长公共子序列的长度,还要用一个g[i][j]来表示方案数,具体的话程序里写吧。。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #define mod 100000000;
    using namespace std;
    char a[10000],b[10000];
    long long g[2][6000],f[2][6000];
    int q,p2,p1,k1,k2,k3;
    int main()
    {
      scanf("%s%s",a+1,b+1);
      int p1=0;
      int n=strlen(a+1)-1,m=strlen(b+1)-1;//记录输入的长度
      for (int i=0;i<=m;i++) g[0][i]=1;//一边没有,另一边为一个的方案数为1; 
      g[1][0]=1;
    //这道题需要用滚动数组,所以我们只需计录之前的状态就可以了
      for (int i=1;i<=n;i++)
      {
           p2=p1; p1=p1^1;
    //这里我本来用的是减法,结果悲催的发现时间超限了。。。所以还是乖乖
    //用位运算吧,p1表示当前状态,p2表示上一次的状态。
       for (int j=1;j<=m;j++)
        if (a[i]==b[j])//如果说当前相等的话
        {
             f[p1][j]=max(f[p1][j],f[p2][j-1]+1);
    //这一次的方案数一定包括f[p2][j-1];
             if (f[p1][j]==f[p1][j-1]) k1=1; else k1=0;
             if (f[p1][j]==f[p2][j]) k2=1; else k2=0;
    //继续判断其他情况如果相等的话才能加上相应的方案数
             g[p1][j]=(g[p2][j-1]+k1*g[p1][j-1]+k2*g[p2][j])%mod;
        }
        else 
        {
            f[p1][j]=max(f[p1][j-1],f[p2][j]);
            if (f[p1][j]==f[p1][j-1]) k1=1; else k1=0;
    //如果公共序列的长度没变,但是位置已经进行了移动,那就 加上上次的方案数。      
             if (f[p1][j]==f[p2][j]) k2=1; else k2=0;
             if (f[p1][j]==f[p2][j-1]) k3=-1; else k3=0;
             g[p1][j]=(k3*g[p2][j-1]+k1*g[p1][j-1]+k2*g[p2][j])%mod;
        }
      }
      cout<<f[p1][m]<<endl;  cout<<g[p1][m]<<endl;
      return 0;
    } 
  • 相关阅读:
    MvvmLight:Command
    TreeView控件
    visual studio背景色
    公共语言运行时
    颜色列表
    自定义控件【旋转按钮,带圆角的边框】
    Loding Animation
    ComboBox前台xaml绑定数据
    Blend一些属性图解
    找到视觉树的方法
  • 原文地址:https://www.cnblogs.com/2014nhc/p/6513644.html
Copyright © 2020-2023  润新知