(leetcode) 2478. 完美分割的方案数( dp )

Posted issue是fw

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了(leetcode) 2478. 完美分割的方案数( dp )相关的知识,希望对你有一定的参考价值。

link


题意

把一个字符串切割为k段, 每段至少长minLength, 且段以一个质数开始, 以非质数结束.

问切割方案. ( n<=2000)


定义 f [ i ] [ j ] f[i][j] f[i][j]表示把前 i i i个字符分为 j j j段的方案

这样每次转移需要枚举一个 q q q [ q + 1 , j ] [q+1,j] [q+1,j]自成一段, 转移为

f [ i ] [ j ] + = f [ q ] [ j − 1 ] f[i][j] +=f[q][j-1] f[i][j]+=f[q][j1]

复杂度为 O ( n 3 ) O(n^3) O(n3), 不过这个转移显然是可以优化的.

观察这个转移, 符合条件的 q q q

q < = i − m i n L e n g t h    & &    s [ q ] ∈ [ 2 , 3 , 5 , 7 ] q<=i-minLength\\ \\ \\&\\&\\ \\ s[q]\\in[2,3,5,7] q<=iminLength  &&  s[q][2,3,5,7]

那么新开一个前缀和数组, p r e [ i ] [ j ] = ∑ q < = i & & s [ q ] ∈ [ 2 , 3 , 5 , 7 ] f [ q ] [ j ] pre[i][j]=\\sum\\limits_q<=i\\&\\&s[q]\\in[2,3,5,7] f[q][j] pre[i][j]=q<=i&&s[q][2,3,5,7]f[q][j](这里 s [ q ] s[q] s[q]表示第 q + 1 q+1 q+1个字符)

转移为(当 s [ i − 1 ] s[i-1] s[i1]不为质数时)

f [ i ] [ j ] = p r e [ i − m i n L e n g t h ] [ j − 1 ] f[i][j] = pre[i-minLength][j-1] f[i][j]=pre[iminLength][j1]

然后其实这个 p r e pre pre数组很好维护. 因为根据转移, 用到的 i − m i n L e n g t h i-minLength iminLength是递增的

所以此时可以把 p r e [ i − m i n L e n g t h ] [ . . . . . ] pre[i-minLength][.....] pre[iminLength][.....]的值视为已知, 转移为

p r e [ i ] [ j − 1 ] = p r e [ i − 1 ] [ j − 1 ] + f [ i − m i n L e n g t h ] [ j − 1 ] pre[i][j-1] = pre[i-1][j-1]+f[i-minLength][j-1] pre[i][j1]=pre[i1][j1]+f[iminLength][j1]

复杂度 O ( n 2 ) O(n^2) O(n2)

class Solution 
public:
    static const int maxn = 2009;
    const int mod = 1e9+7;
    int pre[maxn][maxn],f[maxn][maxn];
    bool iszhi(char c)
        int x = c-'0';
        if( x!=2 && x!=3 && x!=5 && x!=7 )
            return false;
        return true;
    
    int beautifulPartitions(string s, int k, int minLength) 
        /*
        f[i][j]表示前i个字符分为j段的方案
        从f[q][j-1]转移而来, 要求q+1是质数, j是非质数

        pre[x][j]表示q<=x, 且x+1为质数的f[q][j]和
        */
        f[0][0] = 1;
        int n = s.size();
        for(int i=minLength;i<=n;i++)
            int zhi = iszhi( s[i-1] );
            int x = i-minLength;
            for(int j=1;j<=i;j++)
                if( x-1>=0 )
                    pre[x][j-1] = pre[x-1][j-1];
                if( iszhi( s[i-minLength] ) )
                    pre[x][j-1] = ( pre[x][j-1]+f[i-minLength][j-1] )%mod;
                if( !zhi )
                    f[i][j] = pre[i-minLength][j-1]; // f[q][j-1]的和, 满足q+1为质数
                if( iszhi( s[i] ) ) pre[i+minLength][j] += f[i][j];
            
        
        return f[n][k];
    
;

以上是关于(leetcode) 2478. 完美分割的方案数( dp )的主要内容,如果未能解决你的问题,请参考以下文章

Leetcode 中的完美正方形

Python|Leetcode《507》|完美数

LeetCode 507 完美数[枚举] HERODING的LeetCode之路

LeetCode:507. 完美数————简单

《LeetCode之每日一题》:252.完美数

LeetCode 507 完美数[枚举] HERODING的LeetCode之路