题解:CF2205E Simons and Dividing the Rhythm
退役一年忘了 KMP 怎么写,痛失 100pts。
首先我们注意到,统计有多少个
所以我们设
然后我们发现去重这个问题不是很好办。经过思考,我们发现如果最后一段形如
所以我们枚举最后一段
那么如何判断这一段不存在非平凡 border 呢?我们可以一边 DP 一边使用 KMP 快速计算前缀函数,这样时间复杂度就变成
代码如下。
#include<bits/stdc++.h>
#define MOD 998244353
using namespace std;
int a[8005],dp[8005];
int nxt[8005],n;
int mian(){
memset(nxt,0,sizeof nxt);
memset(dp,0,sizeof dp);
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
dp[0]=1;
for(int i=1;i<=n;i++){
int m=n-i+1;
nxt[0]=-1;
for(int j=0,k=-1;j<m;){
if(k==-1||a[i+j]==a[i+k]) nxt[++j]=++k;
else k=nxt[k];
}
for(int j=1;j<=m;j++){
if(nxt[j]==0){
int r=i+j-1;
dp[r]=(dp[r]+dp[i-1])%MOD;
}
}
}
cout<<dp[n]<<'\n';
return 0;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int T;
cin>>T;
while(T--) mian();
}