zoukankan      html  css  js  c++  java
  • Solution -「Gym 102759G」LCS 8

    (mathcal{Description})

      Link.

      给定 (m),和长度为 (n),字符集为大写字母的字符串 (s),求字符集相同且等长的字符串 (t) 的数量,使得 (s,t) 的 LCS 长度不小于 (n-m)。答案模 ((10^9+7))

      (nle5 imes10^4)(mle3)

    (mathcal{Solution})

      有个傻瓜怕不是忘了 DP of DP 这种东西。

      LCS 的 DP 信息是很方便压缩储存的,在决策 (t_{i+1}) 时,我们希望知道 (g_{i,max{0,i-m}..min{n,i+m}})(g_{i,j})(s[:i])(t[:j]) 的 LCS),记录第一个位置和其对应下标的差值(不超过 (m))以及后面位置的差分((01) 状态),可以得到一个 ((m+1)2^{2m}) 的压缩,转移枚举在这 (mathcal O(m)) 个内的字符,整体转移不在的字符,最劣复杂度为 (mathcal O(nm^22^{2m})),不过明显跑不满。

    (mathcal{Code})

      写得很丑就试了 qwq。

    /*~Rainybunny~*/
    
    #include <cstdio>
    #include <cassert>
    #include <cstring>
    
    #define rep( i, l, r ) for ( int i = l, rep##i = r; i <= rep##i; ++i )
    #define per( i, r, l ) for ( int i = r, per##i = l; i >= per##i; --i )
    
    const int MAXN = 5e4, MAXM = 3, MOD = 1e9 + 7;
    int n, m, f[2][MAXM + 1][1 << 2 * MAXM];
    char str[MAXN + 5];
    
    /*
    f(i,i-m), f(i,j-m+1), ..., f(i,i+m)
        x   ,    +[0]   , +[...], +[2m-1]
    */
    
    inline int imin( const int a, const int b ) { return a < b ? a : b; }
    inline int imax( const int a, const int b ) { return a < b ? b : a; }
    inline int mul( const int a, const int b ) { return int( 1ll * a * b % MOD ); }
    inline void addeq( int& a, const int b ) { ( a += b ) >= MOD && ( a -= MOD ); }
    
    int main() {
        scanf( "%s %d", str + 1, &m ), n = int( strlen( str + 1 ) );
        str[0] = -1; rep ( i, 1, n ) str[i] -= 'A';
    
        f[0][0][0] = 1;
        for ( int i = 0, sta = 0; i < n; ++i, sta ^= 1 ) {
            rep ( j, 0, m ) rep ( S, 0, ( 1 << 2 * m ) - 1 ) {
                int& cur = f[sta][j][S];
                if ( !cur ) continue;
                // printf( "f(%d,%d,%d)=%d
    ", i, j, S, cur );
                static bool vis[26] = {}; int cnt = 0;
                int tp = imax( i - m, 0 ), sp = imax( i - m + 1, 0 ), u, v;
    
                rep ( t, sp, imin( i + m + 1, n ) ) if ( t && !vis[str[t]] ) {
                    int c = str[t]; vis[c] = true, ++cnt;
                    int las[2] = { imax( i - m, 0 ) - j, 0 }, fir = 0, T = 0;
                    // f(i,j)=max{f(i-1,j),f(i,j-1),f(i-1,j-1)+1}.
                    rep ( k, sp, imin( i + m + 1, n ) ) {
                        u = las[0] + ( S >> ( k - tp - 1 ) & 1 );
                        v = imax( imax( las[1], u ), las[0] + ( str[k] == c ) );
                        if ( k == sp ) {
                            fir = k - v;
                            if ( fir > m ) break;
                        } else T |= ( v > las[1] ) << ( k - sp - 1 );
                        las[0] = u, las[1] = v;
                    }
                    if ( fir <= m ) addeq( f[!sta][fir][T], cur );
                }
                {
                    int las[2] = { imax( i - m, 0 ) - j, 0 }, fir = 0, T = 0;
                    rep ( k, sp, imin( i + m + 1, n ) ) {
                        u = las[0] + ( S >> ( k - tp - 1 ) & 1 );
                        v = imax( las[1], u );
                        if ( k == sp ) {
                            fir = k - v;
                            if ( fir > m ) break;
                        } else T |= ( v > las[1] ) << ( k - sp - 1 );
                        las[0] = u, las[1] = v;
                    }
                    if ( fir <= m ) addeq( f[!sta][fir][T], mul( cur, 26 - cnt ) );
                }
    
                rep ( t, sp, imin( i + m + 1, n ) ) if ( t ) vis[str[t]] = false;
                cur = 0;
            }
        }
    
        int ans = 0;
        rep ( i, 0, m ) rep ( S, 0, ( 1 << 2 * m ) - 1 ) {
            // if ( f[n & 1][i][S] )
            //     printf( "f(%d,%d,%d)=%d
    ", n, i, S, f[n & 1][i][S] );
            assert( !f[n & 1][i][S] || !( S >> m ) );
            if ( imax( n - m, 0 ) - i + __builtin_popcount( S ) >= n - m ) {
                addeq( ans, f[n & 1][i][S] );
            }
        }
        printf( "%d
    ", ans );
        return 0;
    }
    
    
  • 相关阅读:
    10. Regular Expression Matching
    9. Palindrome Number (考虑负数的情况)
    8. String to Integer (整数的溢出)
    7. Reverse Integer (整数的溢出)
    LeetCode Minimum Size Subarray Sum
    LeetCode Course Schedule II
    Linux 文件缓存 (一)
    LeetCode Tries Prefix Tree
    Linux : lsof 命令
    LeetCode Binary Tree Right Side View
  • 原文地址:https://www.cnblogs.com/rainybunny/p/15145939.html
Copyright © 2011-2022 走看看