zoukankan      html  css  js  c++  java
  • [USACO12JAN]视频游戏的连击Video Game Combos(AC自动机+DP)

    Description

    贝西正在打格斗游戏。游戏里只有三个按键,分别是“A”、“B”和“C”。游戏中有 N 种连击 模式,第 i 种连击模式以字符串 Si 表示,只要贝西的按键中出现了这个字符串,就算触发了一次连 击模式。不 同的连击模式是独立计算的,如果几个连击模式同时出现在贝西的按键顺序里,就算有重 叠部分, 也可以同时算作触发了多个模式。

    假如有三个连击模式,分别是“AB”,“BA”,“ABC”,而贝西按下了“ABABC”,那么她一共 触发了四次 连击。假设贝西一共可以按 K 次键,那么她最多能触发多少次连击呢?

    Solution

    将字符串建立AC自动机

    用dp[i][j]表示长度为i当前位置在自动机上j号节点上的连击数

    mark[i]表示自动机上i号节点包括它的fail树上可获得的连击数

    那么dp[i][T[j][k]]=max{dp[i-1][j]+mark[T[i][k]]}

    Code

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    
    int n,m,T[520][4],fail[520],mark[520],tot=1,q[520],f[1010][520],Ans;
    char s[20];
    
    void Insert(){
    	scanf("%s",s);
    	int now=1,len=strlen(s);
    	for(int i=0;i<len;++i){
    		if(!T[now][s[i]-64]) T[now][s[i]-64]=++tot;
    		now=T[now][s[i]-64];
    	}
    	mark[now]++;
    }
    
    void getfail(){
    	for(int i=1;i<=3;++i) T[0][i]=1;
    	int k,now,h=0,t=0;q[++t]=1;
    	while(h<t){
    		now=q[++h];
    		for(int i=1;i<=3;++i)
    			if(T[now][i]){
    				k=fail[now];
    				while(!T[k][i]) k=fail[k];
    				fail[q[++t]=T[now][i]]=T[k][i];
    			}else T[now][i]=T[fail[now]][i];
    		mark[now]+=mark[fail[now]];
    	}		
    }
    
    int main(){
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;++i) Insert();
    	getfail();
    	memset(f,128,sizeof(f));
    	f[0][1]=0;
    	for(int i=1;i<=m;++i)
    		for(int j=1;j<=tot;++j)
    			for(int k=1;k<=3;++k)
    				f[i][T[j][k]]=max(f[i][T[j][k]],f[i-1][j]+mark[T[j][k]]);
    	for(int i=1;i<=tot;++i) Ans=max(Ans,f[m][i]);
    	printf("%d
    ",Ans);
    	return 0;
    }
    
  • 相关阅读:
    IfcFlowDirectionEnum
    QAxWidget
    IfcDistributionFlowElementType
    IfcBuildingElementProxy 概念用法
    opencv图片旋转90度
    IfcMaterialList
    IfcDistributionChamberElement
    IfcArithmeticOperatorEnum
    FileWriter
    IfcDistributionChamberElementType
  • 原文地址:https://www.cnblogs.com/void-f/p/8969097.html
Copyright © 2011-2022 走看看