题解:P10581 [蓝桥杯 2024 国 A] 重复的串
单串 ACAM(可能是 KMP 自动机)+ 矩阵优化 dp。
我们设
朴素转移是容易的。注意正好匹配时的边界问题。
然后发现
- 如何构造当前字符串长为
k 时的答案矩阵(设为B_k )和转移矩阵(设为A )(下标从0 开始编号)?
:::error[错误解法]
设
发现各行之间相互独立,上一行不能转移到下一行,意味着当匹配成功时无法正确转移,次数无法被更新。卒。
:::
正确解法:
设
这样当匹配成功时,次数可以正确被更新,转移正确。
然后构造转移矩阵,先初始化为
令
所以匹配
然后对于每个
对于
然后对这个矩阵求它的
答案矩阵
Code:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int Size=(1<<20)+1;
char buf[Size],*p1=buf,*p2=buf;
char buffer[Size];
int op1=-1;
const int op2=Size-1;
#define getchar() \
(tt == ss && (tt=(ss=In)+fread(In, 1, 1 << 20, stdin), ss == tt) \
? EOF \
: *ss++)
char In[1<<20],*ss=In,*tt=In;
inline int read()
{
int x=0,c=getchar(),f=0;
for(;c>'9'||c<'0';f=c=='-',c=getchar());
for(;c>='0'&&c<='9';c=getchar())
x=(x<<1)+(x<<3)+(c^48);
return f?-x:x;
}
inline void write(int x)
{
if(x<0) x=-x,putchar('-');
if(x>9) write(x/10);
putchar(x%10+'0');
}
#ifndef ONLINE_JUDGE
#define ONLINE_JUDGE
#endif
const int N=31*3,mod=998244353;
int t[N][26];
int tot;
int fail[N];
struct Martix{
int a[N][N]={};
}I;
Martix operator*(const Martix &x,const Martix &y)
{
Martix ans;
const int base=(tot+1)*3;
memset(ans.a,0,sizeof(ans.a));
for(int i=0;i<base;i++)
for(int j=0;j<base;j++)
for(int k=0;k<base;k++)
(ans.a[i][j]+=x.a[i][k]*y.a[k][j]%mod)%=mod;
return ans;
}
void insert(const string &s)
{
int nw=0;
for(char i:s)
{
if(!t[nw][i-'a']) t[nw][i-'a']=++tot;
nw=t[nw][i-'a'];
}
}
Martix build()
{
queue<int> q;
Martix ans;
memset(ans.a,0,sizeof(ans.a));
for(int i=0;i<26;i++)
{
if(t[0][i]) q.push(t[0][i]);
}
while(q.size())
{
int nw=q.front();
q.pop();
for(int i=0;i<26;i++)
{
if(t[nw][i])
{
fail[t[nw][i]]=t[fail[nw]][i];
q.push(t[nw][i]);
}
else t[nw][i]=t[fail[nw]][i];
}
}
const int base=tot+1;
for(int i=0;i<tot;i++)
for(int j=0;j<26;j++)
{
ans.a[i][t[i][j]]+=1;
ans.a[i+base][t[i][j]+base]+=1;
ans.a[i+base+base][t[i][j]+base+base]+=1;
}
for(int i=tot;i==tot;i++)
for(int j=0;j<26;j++)
{
ans.a[i][t[i][j]+base]+=1;
ans.a[i+base][t[i][j]+base+base]+=1;
}
return ans;
}
Martix ksm(Martix x,int p)
{
Martix ans=I;
while(p)
{
if(p&1) ans=ans*x;
x=x*x;
p>>=1;
}
return ans;
}
// void output(Martix x)
// {
// cout<<"\n------------------------------------\n\n";
// for(int i=0;i<(tot+1)*3;i++,cout<<"\n")
// for(int j=0;j<(tot+1)*3;j++)
// cout<<x.a[i][j]<<" ";
// // cout<<"\n------------------------------------\n\n";
// }
signed main()
{
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
#endif
memset(I.a,0,sizeof(I.a));
for(int i=0;i<N;i++) I.a[i][i]=1;
string s;
int n;
cin>>s>>n;
insert(s);
Martix x=build();
Martix ans=ksm(x,n);
int nw=0;
int base=tot+1;
for(int i=2*base-1;i<3*base-1;i++) (nw+=ans.a[0][i])%=mod;
cout<<nw<<"\n";
return 0;
}