AcWing 1052. 设计密码

//f[i][j]表示前 i 个字符与字符串匹配长度为 j 时的方案数
#include <cstring>
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
const int N=55,mod=1e9+7;;
int ne[N];//KMP中的next数组
char str[N];//子串
int f[N][N];//表示对于枚举到的那个点的某个状态的解
int  main() {
    int n,m;
    cin >> n >> str+1;
    m=strlen(str+1);
    for(int i=2,j=0; i<=m; i++) {
        while(j&&str[i]!=str[j+1])j=ne[j];
        if(str[i]==str[j+1])j++;
        ne[i]=j;
    }
    f[0][0]=1;
    for(int i=0; i<n; i++) { //枚举当前密码的长度 
        for(int j=0; j<m; j++) { //枚举子串中的位置,也就是当前密码,与子串匹配的长度 
            for(char k='a'; k<='z'; k++) { //枚举i处的字符
                int u=j;//k要和 str[u+1]匹配,所以从0开始 
                while(u&&k!=str[u+1]) u=ne[u];
                if(str[u+1]==k)u++;
                if(u<m) { //说明没有出现过子串
                    f[i+1][u]=(f[i+1][u]+f[i][j])%mod;//这里最后的状态的f[i+1][u],所以更新的是这个值
                }
            }
        }
    }
    int res=0;
    for(int i=0; i<m; i++)res = (res + f[n][i]) % mod; //把所有的情况加起来
    cout << res;
}
原文地址:https://www.cnblogs.com/QingyuYYYYY/p/12024633.html