You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

41 lines
1.8 KiB

2 years ago
#include <bits/stdc++.h>
using namespace std;
const int N = 55;
const int MOD = 1e9 + 7;
int n, ne[N];
int f[N][N];
char p[N];
int res;
int main() {
scanf("%d %s", &n, p + 1); // 读入模式串,存入到p数组中下标从1开始
int m = strlen(p + 1); // 模式串的长度,读到\0结束会自动计算出p串的长度
// kmp利用模式串求ne数组【模板】
for (int i = 2, j = 0; i <= m; i++) {
while (j && p[i] != p[j + 1]) j = ne[j];
if (p[i] == p[j + 1]) j++;
ne[i] = j;
}
f[0][0] = 1; // 递推起点,文本串0个字符模板串0个字符此时方案数是1其它状态都是0种方案
// 开始填充dp表,为什么i,j都要从0开始呢这其实要先看一下状态转移方程f[i][j]出现在了方程中,而初始值是边界
// f[0][0]=1,所以填表的时候自然也就是从i=0,j=0开始才能使用上初始值
for (int i = 0; i < n; i++) // 阶段
for (int j = 0; j < m && j <= i; j++) // 匹配长度,需要注意的是完成一个字符ch的匹配则j++,所以j的上限是m-1,以达到f[n][m]的最终状态
for (char ch = 'a'; ch <= 'z'; ch++) { // 准备填充的下一个字符ch
int u = j; // 要退到哪里去呢?
while (u && ch != p[u + 1]) u = ne[u]; // 不断回退,找到新起点
if (ch == p[u + 1]) u++; // 如果匹配下一个字符
f[i + 1][u] = (f[i + 1][u] + f[i][j]) % MOD;
}
// 枚举源串长度是n, 模式串匹配度不足m的累加
for (int i = 0; i < m; i++) res = (res + f[n][i]) % MOD;
cout << res << endl;
return 0;
}