题解:CF191A Dynasty Puzzles
CF191A 题解
题面
题意
给定 n 个字符串,将其中一些字符串取出来并拼接在一起,满足拼接的前面一个字符串的结尾与拼接的后面一个字符串的开头相同,且拼接成的字符串的收尾相同。
例子:asc cdlaks sloa。
(无特殊意义,随便举的例子。)
思路
一看到这题就想到了 DP。
于是,设了一个二维数组 f,fl,r 表示字母 l 到字母 r 的最大长度。(就是以字符 l 开头,字符 r 结尾的字符串的最大长度)其中,字母均用数字表示。
所以对于一个字符数组 s,len 为它的长度,有:
f[s[1]][s[len−1]]=len。
接下来要考虑转移的式子:
对于一个字符串(从 1 开始输入),设 l=s[1]−97+1,r=s[len]−97+1(因为 a 的 ASCLL 码为 97),枚举所有可能的开头 i(i∈[1,26]),有两种情况:
- 不将这个字符串接入:则 f[i][r]=f[i][r];
- 将这个字符串接入:则 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 啦。
总结
- 用数字表示字母。
- 线性 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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现