P3041 [USACO12JAN]视频游戏的连击Video Game Combos
看到匹配,当然用AC自动机
常我们有文本串,这里仅给出长度,怎么计算得分呢
按模式串建自动机,跑一边(dp),字符集较小,都不需要统计每个点的值
直接往上扫累加就行
**My complete code: **
#include<cstdio>
#include<queue>
#include<string>
#include<cstring>
using namespace std;
typedef long long LL;
const LL maxn=1100;
inline LL Read(){
LL x=0,f=1; char c=getchar();
while(c<'0'||c>'9'){
if(c=='-') f=-1; c=getchar();
}
while(c>='0'&&c<='9'){
x=(x<<3)+(x<<1)+c-'0'; c=getchar();
}return x*f;
}
LL n,K,ans,nod;
LL son[maxn][5],val[maxn],fail[maxn],dp[maxn][maxn];
bool visit[maxn][maxn];
char s[maxn];
inline void Build(char *s){
LL len=strlen(s),u=0;
for(LL i=0;i<len;++i){
LL c=s[i]-'A';
if(!son[u][c])
son[u][c]=++nod;
u=son[u][c];
}
++val[u];
}
inline void Bfail(){
queue<LL> que;
for(LL i=0;i<3;++i)
if(son[0][i])
que.push(son[0][i]);
while(que.size()){
LL u=que.front(); que.pop();
for(LL i=0;i<3;++i){
LL v=son[u][i];
if(v){
fail[v]=son[fail[u]][i];
que.push(v);
}else
son[u][i]=son[fail[u]][i];
}
}
}
inline LL Get(LL v,LL sum){
while(v)
sum+=val[v],
v=fail[v];
return sum;
}
int main(){
n=Read(),K=Read();
for(LL i=1;i<=n;++i){
scanf(" %s",s);
Build(s);
}
Bfail();
visit[0][0]=true;
for(LL i=0;i<K;++i){
for(LL j=0;j<=nod;++j){
if(!visit[i][j])
continue;
for(LL k=0;k<3;++k){
LL v=son[j][k];
dp[i+1][v]=max(dp[i+1][v],Get(v,dp[i][j]));
visit[i+1][v]=true;
}
}
}
for(LL i=1;i<=nod;++i)
ans=max(ans,dp[K][i]);
printf("%lld",ans);
return 0;
}/*
3 7
ABA
CB
ABACB
4
*/