[20052006-ptz] Decoding Martian Messages

news/2025/2/12 3:25:19/文章来源:https://www.cnblogs.com/YzaCsp/p/18706267

前言

有点神奇的一个题, 不太会做

思路

给定 \(p_{i, c}\) 表示位置 \(i\) 是字符 \(c\) 的概率, 确定 \(\displaystyle\sum_{c = 1}^{t} p_{i, c} = 1\)
一个有效的信息被定义为任意长度为 \(k\) 的子序列都在集合 \(\mathbb{D}\) 中出现
求一个有效的信息 \(c_1c_2c_3c_4\cdots c_n\) , 使得 \(\displaystyle \prod_{i = 1}^{n} p_{i, c_i}\) 最大

首先我们把 \(\mathbb{D}\) 中的串串丢进字典树上, 对于每一个串串, 我们不难处理出其后缀串串的下一个位置, \(\rm{belike}\):
pEm5rE4.png

我们简单搞一组数据

aba
bab
abb
bba
baa

放到字典树上, 并且把跳跃关系 \((\)\(\color{red}{红边}\)\()\) 连上

pEmvzZR.png

连跳跃关系是 \(\mathcal{O} (dt)\) 的, 反正不超时当常数

事实上我们可以把图简化成这样, 不影响答案
pEmxYes.png

考虑一组合法的解, 就是对这个图的一种长为 \(n\) 的遍历
把遍历顺序分层, 不难想到每一层都用概率最大的, 这样贪心下去, 但是是否正确
显然不正确, 但是我们可以考虑正确性更好的图上 \(\rm{dp}\)

\(dp_{i, j}\) 表示对于位置 \(i\) , 当前在字典树的 \(j\) 节点的最优方案, 每次转移显然可以跳不止一个位置
空间复杂度是 \(\mathcal{O} (dkn)\) 的, 一会看着优化

不难发现, 如果我们优化状态, 令 \(dp_{i, j}\) 表示对于位置 \(i\) , 当前在 \(j\) 个字符串的开头, 一样可以转移
把字典树上的操作用数组映射好, 不影响转移

然后简单转移即可

实现

直接给出代码

#include <bits/stdc++.h>
const int MAXN = 1005;
const int MAXD = 205;
const int MAXT = 30;int d, k, t, n;
long double pr[MAXN][MAXT];std::string str[MAXD];
std::map<std::string, int> hash;int go[MAXD][MAXT], last[MAXN][MAXD];
long double dp[MAXN][MAXD];int main()
{freopen("decoding.in", "r", stdin);freopen("decoding.out", "w", stdout);scanf("%d %d %d", &d, &k, &t);for (int i = 0; i < d; i++) std::cin >> str[i], hash[str[i]] = i;memset(go, -1, sizeof(go));for (int i = 0; i < d; i++) {std::string tmp = str[i].substr(1);for (int j = 0; j < t; j++) {tmp += (char)('a' + j);if (hash.find(tmp) != hash.end()) go[i][j] = hash[tmp];tmp.pop_back();}}scanf("%d", &n);for (int i = 0; i < n; i++) for (int j = 0; j < t; j++) scanf("%Lf", &pr[i][j]);/*初始化*/for (int i = 0; i < d; i++) {dp[k - 1][i] = 1.0;for (int j = 0; j < k; j++) dp[k - 1][i] *= pr[j][str[i][j] - 'a'];}for (int i = k - 1; i < n - 1; i++) for (int j = 0; j < d; j++) for (int c = 0; c < t; c++) {if (!(~go[j][c])) continue;int to = go[j][c];if (dp[i + 1][to] < dp[i][j] * pr[i + 1][c]) dp[i + 1][to] = dp[i][j] * pr[i + 1][c], last[i + 1][to] = j;}long double ans = 0.0;int id = -1;for (int i = 0; i < d; i++) {if (dp[n - 1][i] > ans) {ans = dp[n - 1][i];id = i;}}if (ans <= 0) {puts("---");return 0;}int cur = n - 1;std::string res;while (cur > k - 1) {res = str[id].back() + res;id = last[cur][id];cur--;}res = str[id] + res;std::cout << res << '\n';return 0;
}

总结

图上的 最小 / 最大 问题, 尝试使用图上 \(\rm{dp}\) 解决
贪心不正确的时候, 考虑加一维上 \(\rm{dp}\)

\(last\) 数组是经典的回溯输出方案, 见得不多

本题中的节约空间方法:
注意到转移并不需要具体你在哪个点, 只需要知道下一个地方在哪里

不难发现两种转移

  • 去这个点在字典树中的下一个点 \((\)\(\color{black}{黑边}\)\()\)
  • 去这个点跳跃后的下一个点 \((\)\(\color{red}{红边}\)\()\)

本质上, 对于一个字符串, \(\color{red}{红边}\)只会从一个字符串的倒数第一个位置连向一个字符串的倒数第二个位置, 两个字符串可能是相同的, 我们利用这个性质

把记录字典树上的点变成记录第 \(i\) 个字符串, 然后转移就直接跳到下一个字符串的倒数第二个位置, 然后简单的走一条黑边到倒数第一个位置即可

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/881276.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2.3 ~ 2.11

长达九天的寒假集训2.3 上午 模拟 欢乐赛。 ACM 赛制,10 道题; 开题。发现 A 是水,直接通过。 看 B,发现 B 就是个背包,爆了两发之后过了。 看 jijidawang 过了 G 就去看 G,发现是线段树,写了一发,没过。 发现了一些问题,改了改,没过。 开始写拍,拍出来发现自己 que…

Joker 智能开发平台再放大招,新作将彻底重塑开发模式

—— 突破传统枷锁,引领开发模式全面革新自前端可视化智能平台重磅发布后,其在行业内的影响力便如涟漪般迅速扩散。凭借着创新的设计理念和过硬的性能表现,这个平台为无数开发者和企业提供了高效且便捷的开发解决方案,收获了满满的赞誉与认可。 如今,Joker 智能开发平台又…

docker/docker-compose下存储卷的使用(CIFS和NFS)

前面说到Linux下的挂载CIFS和NFS,这里就顺道简单记一下docker/docker-compose去挂载CIFS和NFS的方式,当个笔记记录一下。docker去挂载CIFS和NFS,需要使用存储卷,稍微懂一点docker,就知道这个是什么,所以这里我们长话短说。首先,docker存储卷分为管理卷、绑定卷、临时卷。…

Deep深度算命App

Deep深度算命App应用背景与开发动机 最近,DeepSeek R1模型在AI领域引起了广泛的关注。尽管它不是当前最强大的模型之一,但在中文处理方面表现出色。春节期间,我原本计划开发一个基于AI的图像识别程序,但被周围人对DeepSeek R1用于算命应用的高度评价所吸引,尤其是我的小舅…

javaj进阶(中)

java进阶(中) 集合集合的特点可以动态保存任意多个对象,使用比较方便 提供了一系列方便的操作对象的方法:add、remove、set、getjava集合类很多,主要分为两大类,如图LInk(接口) ArrayList(Link实现类)ArrayList 是 Java 中最常用的集合类之一,它实现了 List 接口,基于…

java中awit和sleep的区别和线程安全性问题

awit和sleep的区别 从名称上来讲: awit:等待。 sleep:休眠。 从属关系上来讲: awit:awit这个方法是在对象上,只要是对象,就有这个方法 sleep:sleep是在Thread上,它是在线程上,是一个静态方法使用方式上来讲: awit只能够在同步代码中去使用 sleep可以在任意的地方中去使用从…

[PyTorch] DDP源码阅读

[PyTorch] DDP源码阅读PyTorch的DistributedDataParallel (DDP) 允许多台机器,多台GPU之间的数据并行。本文简单讲解DDP的流程,并从代码层面理解DDP如何访问底层的通信框架。DDP使用单机多进程来控制多个GPU。模型需要能放入单个GPU中。参考了PyTorch 源码解读之 DP & DD…

SQL注入之时间盲注

SQL注入之时间盲注 一、时间盲注原理 时间盲注技术的核心在于巧妙地运用数据库中的时间延迟函数(例如 MySQL 的 SLEEP() 函数或 PostgreSQL 的 PG_SLEEP() 函数)来验证注入条件的有效性。当注入条件成立时,数据库会执行这些延迟函数,从而导致页面响应时间显著增加;反之,若…

P2024 [NOI2001] 食物链(带权并查集)

这道题要用带权并查集,感觉没听懂只能先把自己能懂得写了; 数组b[i]表示i与根节点的关系,//0 : 同类 1:吃 2:被吃#include r1 == r2 && b[x] != b[y]说明x和y在同一集合,但他们与根节点的关系不是一样的,说明他们不是同类,是假话 #include<set> #includ…

2025苹果春季发布会前瞻:新品迭出,Apple Intelligence国行版即将上线!

随着2025年的到来,苹果公司的春季发布会也渐行渐近。作为科技行业的领军企业,苹果每一次的新品发布都备受瞩目。本次春季发布会,苹果预计会带来一系列令人期待的新品,同时,国行Mac用户也将迎来一个重大更新——Apple Intelligence功能的上线。随着2025年的到来,苹果公司的…

Python3测试框架unittest搭配自动化测试报告工具HTMLTestRunner

最近接触到Python的测试框架unittest, 浅浅的学习了一下。 unittest和HTMLTestRunner搭配,可以完成自动化测试的功能并生成自动化测试报告。 一. 简介Python内置的unittest模块,用于编写和执行单元测试。 HTMLTestRunner 是一个用于生成自动化测试报告的工具,扩展了 unittes…