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

Description


给出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);
}

 

相关文章:

  • 2022-12-23
  • 2021-09-15
  • 2022-12-23
  • 2021-10-18
  • 2021-11-09
  • 2021-06-27
  • 2021-12-17
  • 2022-12-23
猜你喜欢
  • 2022-02-28
  • 2022-12-23
  • 2022-01-11
  • 2021-06-07
  • 2022-12-23
  • 2021-08-13
  • 2022-01-15
相关资源
相似解决方案