BZOJ_2580_[Usaco2012 Jan]Video Game_AC自动机+DP

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\n",ans);
}

 

posted @ 2018-05-20 13:13  fcwww  阅读(125)  评论(0编辑  收藏  举报