【USACO12Jan】视频游戏的连击

题面

https://www.luogu.org/problem/P3041

题解

// luogu-judger-enable-o2
#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#define ri register int
#define N 1050
#define K 1050
using namespace std;
int n,k;
char s[20];

struct acautomato{
  int ch[N][3],val[N];
  int nex[N],cnt[N];
  int tot;
  int f[K][N];
  void insert() {
    int now=0;
    for (ri i=1,l=strlen(s+1);i<=l;i++) {
      int c=s[i]-'A';
      if (!ch[now][c]) ch[now][c]=++tot;
      now=ch[now][c];
    }
    cnt[now]++;
  }
  void getfail() {
    queue<int> q;
    while (!q.empty()) q.pop();
    for (ri c=0;c<3;c++) if (ch[0][c]) {
      if (cnt[ch[0][c]]) val[ch[0][c]]=1; else val[ch[0][c]]=0;
      q.push(ch[0][c]);
    }
    while (!q.empty()) {
      int x=q.front(); q.pop();
      for (ri c=0;c<3;c++) {
        int y=ch[x][c];
        if (!y) ch[x][c]=ch[nex[x]][c]; 
        else {
          nex[y]=ch[nex[x]][c];
          if (cnt[y]) val[y]=val[nex[y]]+1; else val[y]=val[nex[y]];
          q.push(y);
        }
      }
    }
  }
  int dp() {
    memset(f,-0x3f,sizeof(f));
    f[0][0]=0;
    int ans=0;
    for (ri i=0;i<=k-1;i++)
      for (ri j=0;j<=tot;j++)
        for (ri c=0;c<3;c++) {
          f[i+1][ch[j][c]]=max(f[i+1][ch[j][c]],f[i][j]+val[ch[j][c]]);
          if (f[i+1][ch[j][c]]>ans) ans=f[i+1][ch[j][c]];
        }
    //for (ri i=0;i<=tot;i++) if (f[k][i]>ans) ans=f[k][i];
    return ans;
  }
} trie;

int main(){
  scanf("%d %d",&n,&k);
  for (ri i=1;i<=n;i++) {
    scanf("%s",s+1);
    trie.insert();
  }
  trie.getfail();
  cout<<trie.dp()<<endl;
  return 0;
}

猜你喜欢

转载自www.cnblogs.com/shxnb666/p/11279616.html