当前位置: 首页 > news >正文

[Usaco2007 Dec]队列变换 题解

[Usaco2007 Dec]队列变换 题解

  • 思路
    • 初步思考
    • 算法优化
    • 一些细节
  • 代码

思路

初步思考

字典序最小问题一般可以贪心,此题中我们贪心的取两边更小的字母。但是出现了一个问题,就是当两边字母相同时,我们无法判断是选左面还是选右面。

接着之前的思路,我们比较第二个字母的大小,如果相等以此类推。最终就是相当于比较以左端点开始的前缀和以右端点结束的后缀反转后的串的字典序,这最坏情况下整个算法是 O ( n 2 ) O(n ^ 2) O(n2) 的。

算法优化

前后缀问题让我们想到后缀数组。我们可以把第一个串和第二个串反转后的串拼在一起,两个串之间加入足够大的字符进行区分。

这样我们求出新串所有后缀的排名后,即可比较前缀后缀的字典序(因为加入了极大字符,比较时即相当于比较极大字符前的部分)。

时间复杂度 O ( n log ⁡ ( n ) ) O(n\log(n)) O(nlog(n))

一些细节

当比较的两个串的最长公共子串有交集时需要考虑一下。有交集意味着原串回文,回文串删哪边都可以,所以无需处理。

代码

#include <iostream>
#include <cstring>
#include <algorithm>using namespace std;const int N = 75010;int n, m;
char s[N];
int sa[N], x[N], y[N], c[N], rk[N];
char ans[N];
int top;void SA()
{n = n * 2 + 2;for (int i = 1; i <= n; i ++ ) c[x[i] = s[i]] ++ ;for (int i = 2; i <= m; i ++ ) c[i] += c[i - 1];for (int i = n; i; i -- ) sa[c[x[i]] -- ] = i;for (int k = 1; k <= n; k <<= 1){int num = 0;for (int i = n - k + 1; i <= n; i ++ ) y[ ++ num] = i;for (int i = 1; i <= n; i ++ )if (sa[i] > k)y[ ++ num] = sa[i] - k;for (int i = 1; i <= m; i ++ ) c[i] = 0;for (int i = 1; i <= n; i ++ ) c[x[i]] ++ ;for (int i = 2; i <= m; i ++ ) c[i] += c[i - 1];for (int i = n; i; i -- ) sa[c[x[y[i]]] -- ] = y[i], y[i] = 0;swap(x, y);x[sa[1]] = 1, num = 1;for (int i = 2; i <= n; i ++ )x[sa[i]] = (y[sa[i]] == y[sa[i - 1]] && y[sa[i] + k] == y[sa[i - 1] + k]) ? num : ++ num;if (num == n) break;m = num;}for (int i = 1; i <= n; i ++ ) rk[sa[i]] = i;n = (n - 2) / 2;
}int main()
{ios :: sync_with_stdio(false);cin.tie(0), cout.tie(0);cin >> n; m = 256;for (int i = 1; i <= n; i ++ ){char ch;cin >> ch;s[i] = s[n * 2 - i + 2] = ch;}s[n + 1] = 'Z' + 1, s[n * 2 + 2] = 'Z' + 2;SA();int l = 1, r = n;while (l <= r){if (l == r){ans[ ++ top] = s[l];break;}if (rk[l] < rk[n * 2 - r + 2]){ans[ ++ top] = s[l];l ++ ;}else{ans[ ++ top] = s[r];r -- ;}}for (int i = 1; i <= top; i ++ ){cout << ans[i];if (i % 80 == 0) cout << '\n'; }return 0;
}
http://www.xdnf.cn/news/594595.html

相关文章:

  • AUTOSAR图解==>AUTOSAR_SRS_PortDriver
  • 硅基计划2.0 学习总结 叁
  • CLIP中的被动学习
  • OpenAI宣布:核心API支持MCP,助力智能体开发
  • memcpy 函数的使用 (C语言)
  • 110kV/630mm2电缆5km的交流耐压试验兼顾110kVGIS开关用
  • 彩礼的异化:婚姻市场中的资本规训与性别政治批判
  • NV013NV024美光固态闪存NV028NV034
  • Tomcat多实例配置
  • 从零开始学习QT——第一步
  • vue组件渲染到iframe里面(同域名下),组件可以在同一项目下维护
  • VPC的作用
  • python调wfdb库读欧洲st-t数据库
  • 让办公更聪明:OA系统如何重塑企业协作模式
  • 第六部分:第五节 - 数据持久化 (基础):管理厨房的原材料库存
  • NACOS2.3.0开启鉴权登录
  • 基于深度学习的无线电调制识别系统
  • 数据库基础面试题(回答思路和面试建议)
  • 小林八股Java集合笔记(8k字概要版)
  • 【调优】Java 调优学习笔记之字符串
  • ollama接口数据返回格式化数据,商品标题,商品详情
  • 八、Linux进程和计划任务管理
  • 【Dify学习笔记】:dify通过ollama加载DeepSeek-R1-32B模型无法加载!终于解决了!!
  • C++ QT生成GIF,处理原始图像RGBA数据,窗口生成简单的动画
  • 练习小项目7:天气状态切换器
  • db_ha执行ha_isready报错authentication method 13 not supported
  • 同步/异步电路;同步/异步复位
  • 从法律视角看湖北理元理律师事务所的债务优化实践
  • Qt5、C++11 获取wifi列表与wifi连接
  • vue3商城类源码分享 期末作业 注册登录,状态管理,搜索,购物车订单页面