BZOJ_2580_[Usaco2012 Jan]Video Game_AC自动机+DP
Description
Bessie is playing a video game! In the game, the three letters 'A', 'B', and 'C' are the only valid buttons. Bessie may press the buttons in any order she likes; however, there are only N distinct combos possible (1 <= N <= 20). Combo i is represented as a string S_i which has a length between 1 and 15 and contains only the letters 'A', 'B', and 'C'. Whenever Bessie presses a combination of letters that matches with a combo, she gets one point for the combo. Combos may overlap with each other or even finish at the same time! For example if N = 3 and the three possible combos are "ABA", "CB", and "ABACB", and Bessie presses "ABACB", she will end with 3 points. Bessie may score points for a single combo more than once. Bessie of course wants to earn points as quickly as possible. If she presses exactly K buttons (1 <= K <= 1,000), what is the maximum number of points she can earn?
给出n个ABC串combo[1..n]和k,现要求生成一个长k的字符串S,问S与word[1..n]的最大匹配数
Input
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.
Output
Line 1: A single integer, the maximum number of points Bessie can obtain.
Sample Input
3 7 ABA CB ABACB
Sample Output
4
先对那些combo串建立AC自动机。
每个节点维护出fail树的子树和。
设F[i][j]表示i个字符,现在在j号节点上的最大匹配数
转移就F[i+1][ch[j][c]]=max(F[i+1][ch[j][c]],F[i][j]+siz[ch[j][c]])即可。
代码:
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define N 1050
#define M 660
int ch[M][3],fail[M],cnt=1,siz[M],f[N][M],n,m,Q[M],l,r;
char w[22];
void insert() {
int i,p=1,lw=strlen(w+1);
for(i=1;i<=lw;i++) {
int &k=ch[p][w[i]-'A'];
if(!k) k=++cnt; p=k;
}
siz[p]=1;
}
void build() {
int p,i;
for(i=0;i<3;i++) ch[0][i]=1;
Q[r++]=1;
while(l<r) {
p=Q[l++];
for(i=0;i<3;i++) {
if(ch[p][i]) fail[ch[p][i]]=ch[fail[p]][i],Q[r++]=ch[p][i];
else ch[p][i]=ch[fail[p]][i];
}
siz[p]+=siz[fail[p]];
}
}
int main() {
scanf("%d%d",&m,&n);
int i,j,k;
for(i=1;i<=m;i++) {
scanf("%s",w+1);
insert();
}
build();
memset(f,0x80,sizeof(f));
f[0][1]=0;
for(i=1;i<=n;i++) {
for(j=1;j<=cnt;j++) {
for(k=0;k<3;k++) {
f[i][ch[j][k]]=max(f[i][ch[j][k]],f[i-1][j]+siz[ch[j][k]]);
}
}
}
int ans=0;
for(i=1;i<=cnt;i++) ans=max(ans,f[n][i]);
printf("%d
",ans);
}