• 【题解】[USACO12JAN]Video Game G


    第一道(AC)自动机(+DP.)

    首先,一个自动机上(DP)的套路是设(dp[i][j])表示长度为(i)匹配到(j)节点的最优得分。

    那么,由于我们已经建好了(Trie)图,我们就应该提前把走到节点(j)的所有连击操作处理出来。

    有一条显然结论:如果在(fail)树上经过了这个串结尾节点中子树中的任意一点,则这次匹配一定会包含这个串。

    换句话说,我们在对每一个节点更新(fail)的时候,其分值应该直接把其(fail)的分值加上。

    于是我们进行(dp.)

    首先初始值都是(-inf,)但对于匹配节点在根的情况应该是(0.)

    至于为什么(dp[0][*])不能赋值为(0,)是因为根本不可能存在这种状态。匹配长度为(0)不可能匹配到其他节点。

    但初始时,不管哪一个节点和(0)匹配,其一定不会有任何分数。根节点本身是一个空节点。

    解决初始值问题,我们可以进行(dp.)

    枚举长度,枚举节点,再枚举字符。对于一个状态,我们应该取所有能到达这个状态的(dp)值的(max.)因为我只能输入(k)个字符。

    剩下的就是模板了。

    #include<bits/stdc++.h>
    using namespace std;
    int dp[5000][2000];
    const int MAXN=4000;
    int pos[MAXN],cnt[MAXN];
    int tot,n;
    char st[MAXN];
    struct Tree{
    	int ch[3],fail;
    }T[MAXN];
    vector<int>to[MAXN];
    int num[MAXN];
    int insert(char *str,int len){
    	int u=0;
    	for(int i=0;i<len;++i){
    		int x=str[i]-'A';
    		if(!T[u].ch[x])T[u].ch[x]=++tot;
    		u=T[u].ch[x];
    	}
    	num[u]++;return u;
    }
    void bfs(){
    	queue<int>q;
    	for(int i=0;i<3;++i){
    		if(T[0].ch[i]){
    			int v=T[0].ch[i];
    			T[v].fail=0;
    			q.push(v);
    		} 
    	}
    	while(!q.empty()){
    		int u=q.front();q.pop();
    		for(int i=0;i<3;++i){
    			if(T[u].ch[i]){
    				int v=T[u].ch[i];
    				T[v].fail=T[T[u].fail].ch[i];
    				q.push(v);
    			}
    			else T[u].ch[i]=T[T[u].fail].ch[i];
    		} 
    		to[T[u].fail].push_back(u);
    		num[u]+=num[T[u].fail];
    	}
    }
    int K;
    
    int main(){
    	scanf("%d%d",&n,&K);
    	for(int i=1;i<=n;++i){
    		scanf("%s",st);
    		int L=strlen(st);
    		pos[i]=insert(st,L);
    	}
    	bfs();
    	memset(dp,128,sizeof(dp));
    	for(int i=0;i<=K;++i)dp[i][0]=0;
    	for(int i=1;i<=K;++i){
    		for(int j=0;j<=tot;++j){
    			for(int k=0;k<3;++k){
    				dp[i][T[j].ch[k]]=max(dp[i][T[j].ch[k]],dp[i-1][j]+num[T[j].ch[k]]); 
    			}
    		}
    	}
    	int ans=0;
    	for(int i=0;i<=tot;++i)ans=max(ans,dp[K][i]);
    	printf("%d
    ",ans);
    	return 0;
    } 
    
  • 相关阅读:
    Java实现 蓝桥杯VIP 算法训练 字符删除
    Java实现 蓝桥杯VIP 算法训练 字符删除
    Java实现 蓝桥杯VIP 算法训练 字符删除
    Java实现 蓝桥杯VIP 算法训练 字符删除
    Java实现 蓝桥杯VIP 算法训练 字符删除
    Java实现 蓝桥杯VIP 算法训练 字符串编辑
    Java实现 蓝桥杯VIP 算法训练 字符串编辑
    Java实现 蓝桥杯VIP 算法训练 字符串编辑
    Java实现 蓝桥杯VIP 算法训练 字符串编辑
    Java实现 蓝桥杯VIP 算法训练 字符串编辑
  • 原文地址:https://www.cnblogs.com/h-lka/p/13503172.html
Copyright © 2020-2023  润新知