题解:P10581 [蓝桥杯 2024 国 A] 重复的串
A7F3jK9pR0xf_ · · 题解
题目传送门
大家好我不会 KMP,所以我使用了 ACAM + 矩阵快速幂通过了此题。
这种做法可以扩展的多个串的情况。
考虑建立原串的 ACAM,建出字典图,记
考虑直接 DP 的时间复杂度是
#include <bits/stdc++.h>
using namespace std;
#define il inline
typedef long long ll;
const int mod = 998244353;
int M;
struct mat
{
ll a[210][210];
friend mat operator * (const mat &n1, const mat &n2)
{
mat n3 = (mat){{{0}}};
for(int i = 0;i < M;++i)
for(int j = 0;j < M;++j)
for(int k = 0;k < M;++k)
n3.a[i][j] = (n3.a[i][j] + n1.a[i][k] * n2.a[k][j] % mod) % mod;
return n3;
}
};
il mat ppow(mat A, mat T, int n)
{
for(;n > 0;T = T * T, n >>= 1)
if(n & 1) A = A * T;
return A;
}
int tr[40][26], cnt[40], fail[40], tot;
il void insert(string s)
{
int root = 0;
for(char c : s)
{
if(!tr[root][c - 'a']) tr[root][c - 'a'] = ++tot;
root = tr[root][c - 'a'];
}
cnt[root]++;
}
queue<int> q;
il void ACAM()
{
for(int i = 0;i < 26;++i)
if(tr[0][i]) q.push(tr[0][i]);
while(q.size())
{
int u = q.front();
q.pop();
cnt[u] += cnt[fail[u]];
for(int i = 0;i < 26;++i)
{
if(tr[u][i])
{
fail[tr[u][i]] = tr[fail[u]][i];
q.push(tr[u][i]);
}
else tr[u][i] = tr[fail[u]][i];
}
}
}
il int calc(int j, int k)
{
return j + (tot + 1) * k;
}
il void print(mat A)
{
for(int i = 0;i < M;++i)
{
for(int j = 0;j < M;++j) cout << A.a[i][j] << " ";
cout << "\n";
}
}
mat A, T;
int main()
{
int n;
string s;
cin >> s >> n;
insert(s);
ACAM();
M = calc(tot, 2) + 1;
A.a[0][0] = 1;
for(int j = 0;j <= tot;++j)
{
for(int c = 0;c < 26;++c)
{
for(int k = 0;k <= 2;++k)
{
int x = k + cnt[tr[j][c]];
if(x <= 2) T.a[calc(j, k)][calc(tr[j][c], x)]++;
}
}
}
// print(T);
A = ppow(A, T, n);
// print(A);
ll ans = 0;
for(int i = calc(0, 2);i <= calc(tot, 2);++i) ans = (ans + A.a[0][i]) % mod;
cout << ans;
return 0;
}