zoukankan      html  css  js  c++  java
  • 【DP】操作集锦

    【题目链接】  传送门

    【题意】

      给出一个长度为 n的字符串,请问长度为k的子序列,中本质不同的有多少?

      比如abba,本质不同的长度为2的串有:ab,aa,bb,ba

    【题解】

      要做到不重不漏。需要借助序列自动机。

    //创建序列自动机 , Next[i]['a'] -> 第 i 个位置 下一个'a' 的位置
    for( int i = n ; i >= 1 ; i -- ){
        for( int j = 0 ; j < 26 ; j ++ )
                Next[i-1][j] = Next[i][j] ;
            Next[i-1][s[i]-'a'] = i ;
    }    

      利用序列自动机,把当前的位置的方案向后传送。

      1、f[i][j],状态表示:表示以s[i]结尾,长度为j的子序列的方案数。

      2、状态计算:f[i][j] = f[i][j] + f[k][j-1]  ,k < i 

      为了方便计算,答案应该在当前位置,更新后面的。

    f[0][0] = 1 ;
    for( int i = 0 ; i <= n ; i++ ){
        for( int j = 0 ; j <= min( k , i ) ; j ++ ){
            for( int c = 0 ; c < 26 ; c ++ ){
                f[Next[i][c]][j+1] = ( f[i][j] + f[Next[i][c]][j+1] ) % mod ;
        }    
      }
    }    

    【具体代码】

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<iostream>
     5 using namespace std;
     6 typedef long long ll ;
     7 const ll mod = 1e9 + 7 ;
     8 const int N = 1e3 + 10;
     9 ll f[N][N] ;
    10 char s[N];
    11 int Next[N][30] , n , k ;
    12 int main()
    13 {
    14     scanf("%d%d",&n,&k);    
    15     scanf("%s",s+1);
    16 
    17     //初始化
    18     for( int i = 1 ; i <= 26 ; i++ )
    19         Next[n][i] = n + 1 ;
    20 
    21     //创建序列自动机 , Next[i]['a'] -> 第 i 个位置 下一个'a' 的位置
    22     for( int i = n ; i >= 1 ; i -- ){
    23         for( int j = 0 ; j < 26 ; j ++ )
    24             Next[i-1][j] = Next[i][j] ;
    25         Next[i-1][s[i]-'a'] = i ;
    26     }
    27     //printf("%d %d %d
    ",Next[0][0],Next[0][1],Next[0][2]);
    28     f[0][0] = 1 ;
    29     for( int i = 0 ; i <= n ; i++ ){
    30         for( int j = 0 ; j <= min( k , i ) ; j ++ ){
    31             for( int c = 0 ; c < 26 ; c ++ ){
    32                 f[Next[i][c]][j+1] = ( f[i][j] + f[Next[i][c]][j+1] ) % mod ;
    33             }
    34         }
    35     }
    36     ll ans = 0 ;
    37     for( int i = k ; i <= n ; i++ ){
    38         ans = ( ans + f[i][k] ) % mod ;
    39     }
    40     printf("%lld
    ",ans);
    41     return 0;
    42 }
    View Code
  • 相关阅读:
    ShellExecuteEx 函数说明
    npm
    Byte和char
    如何高效阅读一个项目
    C++中慎用malloc
    #ifdef
    string
    C++与C混合编译
    git@github.com: Permission denied (publickey).
    connect to host github.com port 22: Connection refused
  • 原文地址:https://www.cnblogs.com/Osea/p/12603623.html
Copyright © 2011-2022 走看看