题解:CF191A Dynasty Puzzles

CF191A 题解

题面

原题传送门

题意

给定 n 个字符串,将其中一些字符串取出来并拼接在一起,满足拼接的前面一个字符串的结尾与拼接的后面一个字符串的开头相同,且拼接成的字符串的收尾相同。

例子:asc cdlaks sloa

(无特殊意义,随便举的例子。)

思路

一看到这题就想到了 DP。

于是,设了一个二维数组 ffl,r 表示字母 l 到字母 r 的最大长度。(就是以字符 l 开头,字符 r 结尾的字符串的最大长度)其中,字母均用数字表示。

所以对于一个字符数组 slen 为它的长度,有:

f[s[1]][s[len1]]=len

接下来要考虑转移的式子:

对于一个字符串(从 1 开始输入),设 l=s[1]97+1,r=s[len]97+1(因为 a 的 ASCLL 码为 97),枚举所有可能的开头 i(i[1,26]),有两种情况:

  1. 不将这个字符串接入:则 f[i][r]=f[i][r]
  2. 将这个字符串接入:则 f[i][r]=f[i][l]+len

两者取最大值即可,所以有:

f[i][r]=max(f[i][r],f[i][l]+len)

枚举完以后,咱们还要在权衡利弊一下,如果 f[l][r]<len,那还不如直接就只要这个字符串,所以枚举完后还要有:

f[l][r]=max(f[l][r],len)

于是,这题就可以 AC 啦。

总结

  1. 用数字表示字母。
  2. 线性 DP。

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
long long n,f[35][35],ans,len,l,r;
//f[l][r] 表示字母 l 到字母 r 的最大长度 
char s[15];
int main(){
	scanf("%lld",&n);
	for(int i=1; i<=n; i++){
		scanf("%s",s+1);
		len=strlen(s+1);
		l=s[1]-'a'+1,r=s[len]-'a'+1;
		for(int j=1; j<=26; j++)
			if(f[j][l]) 
				f[j][r]=max(f[j][r],f[j][l]+len);
		f[l][r]=max(f[l][r],len);
	} 
	for(int i=1; i<=26; i++) ans=max(ans,f[i][i]);
	printf("%lld\n",ans);
	return 0;
} 
posted @   naroto2022  阅读(3)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示
花开如火,也如寂寞。