luogu P3041 [USACO12JAN]视频游戏的连击Video Game Combos

P3041 [USACO12JAN]视频游戏的连击Video Game Combos

题目大意:

给出n个字符串st[1…n],求一个长度为K的字符串,每匹配到st中的字符串就+1分,问最多能加几分

题解

做法十分套路,
先把AC自动机建出来,在建的时候继承一下nxt的信息
然后就是很简单的DP了

code:

// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define N 305
#define C 3
using namespace std;
int ch[N][C], nxt[N], size[N], n, dp[1005][N], tot, K;
string st;
void insert(){ //插♂入
	int p = 0, len = st.length();
	for(int i = 0;i < len; i ++){
		if(!ch[p][st[i] - 'A']) ch[p][st[i] - 'A'] = ++ tot;
		p = ch[p][st[i] - 'A'];
	}
	size[p] ++;//记一下大小
}
queue<int> q;
void build(){//日常建树
	for(int i = 0; i < C; i ++) if(ch[0][i]) q.push(ch[0][i]);
	while(q.size()){
		int u = q.front(); q.pop();
		size[u] += size[nxt[u]];//继承一下nxt的信息,这样匹配一下就行了,不用每次暴力网上跳
		for(int i = 0; i < C; i ++){
			if(ch[u][i]){
				nxt[ch[u][i]] = ch[nxt[u]][i];
				q.push(ch[u][i]);
			}else ch[u][i] = ch[nxt[u]][i];
		}
	}
}
int main(){
	cin >> n >> K;
	for(int i = 1; i <= n; i ++) cin >> st, insert();
	build();
	//DP,dp[i][j] 表示现在是第i位,在AC自动机上的第j个节点,最大的值是多少
	dp[0][0] = 1;//这是个小技巧,先把初值设为1,最后答案再减1,这样就不用吧其他的全都设为-INF了
	for(int i = 0; i < K; i ++)	
		for(int j = 0; j <= tot; j ++){
			if(!dp[i][j]) continue;
			for(int k = 0; k < C; k ++){
				int v = ch[j][k];
				dp[i + 1][v] = max(dp[i + 1][v], dp[i][j] + size[v]);//简单的转移
			}
		}
	int ans = 0;
	for(int i = 0; i <= tot; i ++) ans = max(ans, dp[K][i]);//找最大
	cout << ans - 1;//记得减回一
	return 0;
}

坑点:

貌似没有,就-INF吧

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值