zoukankan      html  css  js  c++  java
  • 【NOIP2015】子串

    本题在洛谷上的链接:https://www.luogu.org/problemnew/show/P2679


    好难的DP题,哎,今年要是遇到这样的DP题就放弃得了。。。

    本来打算像那道统计单词个数一样,先对字符串进行预处理,然后跑DP,想了个思路,复杂度很高,而且代码也不好实现。

    看大佬的博客里,用的方法类似LIS。就是讨论a中第i个字符取不取。

    定义状态dp[i][j][k][s],s=0表示所有的方案数,s=1表示必定取第i个字符的方案数。必须满足a[i]=b[j]才可以取第i个字符,此时dp[i][j][k][1]=dp[i-1][j-1][k-1][0]+dp[i-1][j-1][k][1],否则dp[i][j][k][1]=0;

    dp[i][j][k][0]自然就是dp[i-1][j][k][0]+dp[i][j][k][1],仔细想想的确是对的,但要自己想出来好难啊!

    虽然时间不会超,但空间会炸,需要滚动数组,因为我们发现第1维只用到了i和i-1,所以写成pre和now就好。

    再就是初始化dp[pre][0][0][0]=dp[now][0][0][0]=1,统计方案数的DP初始化最坑了,一般是把一种啥也不干的dp值设为1。

    最后别忘了对1e9+7取模。

     1 #include <cstdio>
     2 
     3 const int maxn = 1005, maxm = 205, maxk = 205, P = 1e9 + 7;
     4 
     5 int dp[2][maxm][maxk][2];
     6 
     7 char a[maxn], b[maxm];
     8 
     9 inline void swap(int &a, int &b) {
    10     int t = a; a = b, b = t;
    11 }
    12 
    13 int main() {
    14     int n, m, k, pre = 0, now = 1;
    15     scanf("%d%d%d%s%s", &n, &m, &k, a + 1, b + 1);
    16     dp[pre][0][0][0] = dp[now][0][0][0] = 1;
    17     for (int i = 1; i <= n; ++i, swap(pre, now))
    18         for (int j = 1; j <= m; ++j)
    19             for (int p = 1; p <= k; ++p) {
    20                 if (a[i] == b[j])
    21                     dp[now][j][p][1] = (dp[pre][j - 1][p - 1][0] + dp[pre][j - 1][p][1]) % P;
    22                 else dp[now][j][p][1] = 0;
    23                 dp[now][j][p][0] = (dp[pre][j][p][0] + dp[now][j][p][1]) % P;
    24             }
    25     printf("%d", dp[pre][m][k][0]);
    26     return 0;
    27 }
    AC代码
  • 相关阅读:
    Handler
    declare-styleable的使用
    Android APK反编译就这么简单 详解(附图)
    webview与js交互
    Android 开源框架ActionBarSherlock 和 ViewPager 仿网易新闻客户端
    eclipse中的.project 和 .classpath文件的具体作用
    android:关于主工程和library project
    block,inline和inline-block概念和区别
    容易被忽略CSS特性
    CSS里常见的块级元素和行内元素
  • 原文地址:https://www.cnblogs.com/Mr94Kevin/p/9815345.html
Copyright © 2011-2022 走看看