【USACO12JAN】—视频游戏的连击Video Game Combos(AC自动机+dp)
描述
贝西在玩一款游戏,该游戏只有三个技能键 “A”“B”“C”可用,但这些键可用形成N种(1 <= N<= 20)特定的组合技。第i个组合技用一个长度为1到15的字符串S_i表示。
当贝西输入的一个字符序列和一个组合技匹配的时候,他将获得1分。特殊的,他输入的一个字符序列有可能同时和若干个组合技匹配,比如N=3时,3种组合技分别为"ABA", “CB”, 和"ABACB",若贝西输入"ABACB",他将获得3分。
若贝西输入恰好K (1 <= K <= 1,000)个字符,他最多能获得多少分?
输入
Line 1: Two space-separated integers: N and K.
Lines 2…N+1: Line i+1 contains only the string S_i, representing combo i.
输出
Line 1: A single integer, the maximum number of points Bessie can obtain.
样例输入
3 7
ABA
CB
ABACB
样例输出
4
提示
The optimal sequence of buttons in this case is ABACBCB, which gives 4 points–1 from ABA, 1 from ABACB, and 2 from CB.
每次暴力枚举下一个字符填什么在自动机上dp就完了
注意下传
#include<bits/stdc++.h>
using namespace std;
#define gc getchar
inline int read(){
char ch=gc();
int res=0,f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
return f?res:-res;
}
#define pb push_back
#define re register
#define cs const
#define ll long long
#define pii pair<int,int>
#define fi first
#define se second
inline void chemx(int &a,int b){
a<b?a=b:0;
}
inline void chemn(int &a,int b){
a>b?a=b:0;
}
const int N=305;
namespace Ac{
int nxt[N][3],fail[N],end[N],tot;
inline void insert(char *s){
int p=0;
for(int i=1,len=strlen(s+1);i<=len;i++){
int c=s[i]-'A';
if(!nxt[p][c])nxt[p][c]=++tot;
p=nxt[p][c];
}
end[p]++;
}
queue<int> q;
inline void build(){
for(int i=0;i<3;i++){
int v=nxt[0][i];
if(v)q.push(v),fail[v]=0;
}
while(!q.empty()){
int p=q.front();q.pop();
for(int c=0;c<3;c++){
int v=nxt[p][c];
if(!v)nxt[p][c]=nxt[fail[p]][c];
else fail[v]=nxt[fail[p]][c],q.push(v);
}
end[p]+=end[fail[p]];
}
}
int f[1005][N];
inline int dp(int n){
memset(f,-1,sizeof(f));
f[0][0]=0;
for(int i=0;i<n;i++)
for(int j=0;j<=tot;j++){
if(f[i][j]==-1)continue;
for(int c=0;c<3;c++)
chemx(f[i+1][nxt[j][c]],f[i][j]+end[nxt[j][c]]);
}int res=0;
for(int i=0;i<=tot;i++)chemx(res,f[n][i]);
return res;
}
}
int n,m;
char s[N];
int main(){
n=read(),m=read();
for(int i=1;i<=n;i++)
scanf("%s",s+1),Ac::insert(s);
Ac::build();
cout<<Ac::dp(m);
}