AcWing 1052. 设计密码

个人理解:f[i][j]已经构造出前i个字母(相当于走了n步),并且当前和T已经匹配到第j个字母的方案。

m为字符串T的长度:

在本题中,根据kmp匹配的思想,j + 1如果可以和当前第i个字母相同,那么j可以跳到j + 1,否则,j就回退,跳到next[j]我们构造的字串无论如何不能与T中第m个字母匹配起来,即j的状态到了m,那就是不合法状态,因为一旦匹配,就说明T成为了S的一个字串,那么就不符合题意了。

所以对于j的状态,只能是0m - 1,那么j与什么有关呢,可以发现,j只与当前i是哪个字符有关,而当前第i个字符可以取值为a-z

结果,就是f[n][i](i[0,m))的累加。

很神奇的一道题,把这个模型记一下。

#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;

const int N = 55, Mod = 1e9 + 7;
int f[N][N];
char str[N];
int match[N], n;

int main() {
    cin >> n >> str + 1;
    int m = strlen(str + 1);
    
    for (int i = 2, j = 0; i <= n; i++) {
        while (j && str[i] != str[j + 1]) j = match[j];
        if (str[i] == str[j + 1]) j++;
        match[i] = j;
    }
    
    f[0][0] = 1;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            for (int k = 'a'; k <= 'z'; k++) {
                int u = j;
                while (u && str[u + 1] != k) u = match[u];
                if (k == str[u + 1]) u++;
                if (u < m) f[i + 1][u] = (f[i + 1][u] + f[i][j]) % Mod; //表示从第i步可以走到第i + 1步
            }
        }
    }
    
    int res = 0;
    for (int i = 0; i < m; i++) res = (res + f[n][i]) % Mod;
    
    cout << res << endl;
    
    return 0;
}
posted @   Xxaj5  阅读(63)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示