SP10502 VIDEO - Video game combos 题解

题目传送门

前置知识

AC 自动机

解法

多模式串匹配考虑 AC 自动机。

fi,j 表示前 i 个字符,当前运行到 AC 自动机的状态 j 时的最大得分。状态转移方程为 fi,k=maxkSon(j){fi1,j+sumk},其中 sumk 表示 fail 树上以 k 结尾的字符串个数。

最终,有 maxi=0tot{fm,i} 即为所求。

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define ull unsigned long long
#define sort stable_sort 
#define endl '\n'
int trie[1000][5],fail[1000],sum[1000],f[2000][1000],tot=0;
char s[1000];
int val(char x)
{
	return x-'A'+1;
}
void insert(char s[],int len)
{
	int x=0,i;
	for(i=1;i<=len;i++)
	{
		if(trie[x][val(s[i])]==0)
		{
			tot++;
			trie[x][val(s[i])]=tot;
		}
		x=trie[x][val(s[i])];
	}
	sum[x]++;
}
void build()
{
	int x,i;
	queue<int>q;
	for(i=1;i<=3;i++)
	{
		if(trie[0][i]!=0)
		{
			fail[trie[0][i]]=0;
			q.push(trie[0][i]);
		}
	}
	while(q.empty()==0)
	{
		x=q.front();
		q.pop();
		for(i=1;i<=3;i++)
		{
			if(trie[x][i]==0)
			{
				trie[x][i]=trie[fail[x]][i];
			}
			else
			{
				fail[trie[x][i]]=trie[fail[x]][i];
				sum[trie[x][i]]+=sum[fail[trie[x][i]]];
				q.push(trie[x][i]);
			}
		}
	}
}
int main()
{
	int n,m,ans=0,i,j,k;
	cin>>n>>m;
	memset(f,-0x3f,sizeof(f));
	for(i=1;i<=n;i++)
	{
		cin>>(s+1);
		insert(s,strlen(s+1));
	}
	build();
	f[0][0]=0;
	for(i=1;i<=m;i++)
	{
		for(j=0;j<=tot;j++)
		{
			if(f[i-1][j]>=0)
			{
				for(k=1;k<=3;k++)
				{
					f[i][trie[j][k]]=max(f[i][trie[j][k]],f[i-1][j]+sum[trie[j][k]]);
				}
			}
		}
	}
	for(i=0;i<=tot;i++)
	{
		ans=max(ans,f[m][i]);
	}
	cout<<ans<<endl;
	return 0;
}	

后记

多倍经验:luogu P3041 [USACO12JAN] Video Game G

posted @   hzoi_Shadow  阅读(11)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
扩大
缩小
点击右上角即可分享
微信分享提示