y总视频里所说的预计算方式。可以将时间复杂度为降为$O(N^2*26)$
#include <iostream>
#include <cstring>
using namespace std;
const int MAXN = 55;
const int module = 1e9 + 7;
int f[MAXN][MAXN];
int trans[MAXN][26];
char p[MAXN];
int N, ne[MAXN];
int main() {
cin >> N >> p + 1;
int m = strlen(p + 1);
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;
}
for (int i = 0; i < m; ++i) {
for (int k = 'a'; k <= 'z'; ++k) {
int u = i;
while (u && p[u + 1] != k) u = ne[u];
if (p[u + 1] == k) ++u;
trans[i][k - 'a'] = u;
}
}
f[0][0] = 1;
for (int i = 1; i <= N; ++i) {
for (char k = 'a'; k <= 'z'; ++k) {
for (int j = 0; j < m; ++j)
{
int u = trans[j][k - 'a'];
if (u != m) f[i][u] = (f[i][u] + f[i - 1][j]) % module;
}
}
}
int ans = 0;
for (int i = 0; i < m; ++i) ans = (ans + f[N][i]) % module;
cout << ans << endl;
return 0;
}
请教一下应该如何理解这个
f[i][u] = (f[i][u] + f[i - 1][j]
呢?首先要知道状态的定义
f[i][u]
是什么意思,f[i][u]
表示的是在长度为i
的的所有字符串中 使得我们的模式串最终停留在位置u
的字符串总数。 而它正是由长度为i-1
的字符串中那些下一次匹配可以转移到u
的位置所转移过来的,trans
矩阵代表当模式串位置在j
时并且当前主串为字母k
的时候 下一次会转移到哪个位置。所以每次trans[j][k - 'a']
等于u
的时候当前的f[i][u]
就需要加上它你这个状态定义与说明,是我看到题解里面写得最清晰明了的,点赞%%%。