P3041 [USACO12JAN]视频游戏的连击Video Game Combos
Posted y2823774827y
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P3041 [USACO12JAN]视频游戏的连击Video Game Combos相关的知识,希望对你有一定的参考价值。
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
*/
以上是关于P3041 [USACO12JAN]视频游戏的连击Video Game Combos的主要内容,如果未能解决你的问题,请参考以下文章
[USACO12JAN]视频游戏的连击Video Game Combos(AC自动机+DP)
视频游戏的连击 [USACO12JAN](AC自动机+动态规划)
洛谷 P3041 [USACO12JAN] Video Game Combos
bzoj 1594: [Usaco2008 Jan]猜数游戏——二分+线段树