BZOJ - 1009: [HNOI2008]GT考试 dp+KMP

题意:

给定字符串ch,问长度为n的字符串,有多少种可能不包含字符串ch

思路:

算是比较经典的dp的题,我们首先容易想到包含这个串的字符串有多少个,但是发现难以实现,

然后我们用递推的方式来直接求解不包含这个串的新串的个数,

令dp[i][j] 表示 我们维护的当前串长度为 i,并且其包含j个字符的后缀 恰好是ch串的前缀,

那么答案ans即为 ans += dp[n][i]  : i in range(0, m-1);

这样,对于第 i+1 个字符(可以是'0'~'9')有10种转移方式,即转移到dp[i+1][x]:x即新的匹配到的位置;这里需要用到kmp以快速得到x   (关于往下一个符号匹配也可以看这个括号匹配的题 https://blog.csdn.net/xiang_6/article/details/81505075

如果已经匹配完了ch串,那我们不对这个串继续往后转移,也就不会对答案做出贡献;

但是因为 n 很大,我们还得推得:dp[i][0],dp[i][1]...dp[i][m-1]   与    dp[i+1][0],dp[i+1][1]...dp[i+1][m-1] 之间的关系;也就是矩阵快速幂的转移方程,

如代码:我们令b[t][i] 表示已经匹配完ch串中的i个字符后,有多少种方法使得下一个匹配完成的是第t个字符

经过快速幂运算后 a[][] 原数组中:a[0][0], a[1][0]...a[m-1][0] 表示的是 dp[n][0],dp[n][1]...dp[n][m-1]

/**************************************************************
    Problem: 1009
    User: xiang_6
    Language: C++
    Result: Accepted
    Time:96 ms
    Memory:1292 kb
****************************************************************/
 
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int n, m, mod;
int p[27];
char ch[27];
int a[27][27], b[27][27];
 
void mul(int a[27][27], int b[27][27], int ans[27][27]) {
    int tmp[27][27];
    for(int i = 0; i < m; ++i) {
        for(int j = 0; j < m; ++j) {
            tmp[i][j] = 0;
            for(int k = 0; k < m; ++k) {
                tmp[i][j] = (tmp[i][j] + a[i][k]*b[k][j]) % mod;
            }
        }
    }
    for(int i = 0; i < m; ++i) {
        for(int j = 0; j < m; ++j) {
            ans[i][j] = tmp[i][j];
        }
    }
}
 
int main() {
    scanf("%d%d%d", &n, &m, &mod);
    scanf("%s", ch+1);
    p[1] = 1, p[2] = 1;
    for(int i = 2; i < m; ++i) {
        int j = p[i];
        while(j>1 && ch[j]!=ch[i]) j = p[j];
        p[i+1] = (ch[i] == ch[j] ? j+1 : 1);
    }
    for(int i = 0; i < m; ++i) {
        for(int j = 0; j <= 9; ++j) {
            int t = i+1;
            while(t > 1 && ch[t]-'0' != j) t = p[t];
            if(ch[t]-'0' != j) t--;
            if(t != m) b[t][i] = (b[t][i]+1)%mod;
        }
    }
    for(int i = 0; i < m; ++i) {
        a[i][i] = 1;
    }
    while(n) {
        if(n&1) mul(a,b,a);
        mul(b,b,b);
        n >>= 1;
    }
    int ans = 0;
    for(int i = 0; i < m; ++i) {
        ans = (ans + a[i][0]) % mod;
    }
    printf("%d\n", ans);
 
    return 0;
}
 
 
 
 
 
 
 
 
 
 
/*
                       .::::.
                     .::::::::.
                    :::::::::::  I want to say...Accepted!
                ..:::::::::::'
              '::::::::::::'
                .::::::::::
           '::::::::::::::..
                ..::::::::::::.
              ``:::::::::::::::·
               ::::``:::::::::'        .:::.
              ::::'   ':::::'       .::::::::.
            .::::'      ::::     .:::::::'::::.
           .:::'       :::::  .:::::::::' ':::::.
          .::'        :::::.:::::::::'      ':::::.
         .::'         ::::::::::::::'         ``::::.
     ...:::           ::::::::::::'              ``::.
    ```` ':.          ':::::::::'                  ::::..
                       '.:::::'                    ':'````..
 
    ******************** 美↑女坐键↓盘 ********************
┌───┐   ┌───┬───┬───┬───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┐
│Esc│   │ F1│ F2│ F3│ F4│ │ F5│ F6│ F7│ F8│ │ F9│F10│F11│F12│ │P/S│S L│P/B│  ┌┐    ┌┐    ┌┐
└───┘   └───┴───┴───┴───┘ └───┴───┴───┴───┘ └───┴───┴───┴───┘ └───┴───┴───┘  └┘    └┘    └┘
┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐ ┌───┬───┬───┐ ┌───┬───┬───┬───┐
│~ `│! 1│@ 2│# 3│$ 4│% 5│^ 6│& 7│* 8│( 9│) 0│_ -│+ =│ BacSp │ │Ins│Hom│PUp│ │N L│ / │ * │ - │
├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤ ├───┼───┼───┤ ├───┼───┼───┼───┤
│ Tab │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │{ [│} ]│ | \ │ │Del│End│PDn│ │ 7 │ 8 │ 9 │   │
├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤ └───┴───┴───┘ ├───┼───┼───┤ + │
│ Caps │ A │ S │ D │ F │ G │ H │ J │ K │ L │: ;│" '│ Enter  │               │ 4 │ 5 │ 6 │   │
├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤     ┌───┐     ├───┼───┼───┼───┤
│ Shift  │ Z │ X │ C │ V │ B │ N │ M │< ,│> .│? /│  Shift   │     │ ↑ │     │ 1 │ 2 │ 3 │   │
├─────┬──┴─┬─┴──┬┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤ ┌───┼───┼───┐ ├───┴───┼───┤ E││
│ Ctrl│    │Alt │         Space         │ Alt│    │    │Ctrl│ │ ← │ ↓ │ → │ │   0   │ . │←─┘│
└─────┴────┴────┴───────────────────────┴────┴────┴────┴────┘ └───┴───┴───┘ └───────┴───┴───┘
*/


猜你喜欢

转载自blog.csdn.net/xiang_6/article/details/81434904