字符串魔法hard(前后缀与贪心)
字符串魔法hard(前后缀与贪心)
链接:https://ac.nowcoder.com/acm/contest/9680/C
来源:牛客网
description:
白浅获得了一个仅由A和B组成的字符串。他可以至多使用一次魔法来改变字符串。 魔法:选择一个子串,满足子串中 A 的数量等于 B
的数量,然后按字典序从小到大排序这个子串,即变成形如AAA…AAABBB…BBB这样的字符串(A和B的数量均与原来的子串相同)。
他想知道,在他至多使用一次魔法后,这个字符串能够出现的最长的字典序不递减的子串的长度为多少。
输入描述: 第一行包含一个整数n,代表字符串的长度。 接下来一行给出一个长度为n的字符串。
1≤n≤200000
输出描述: 输出一行一个正整数表示答案。
Sample:
输入 :
6
AABBAA
输出:
6
解题思路:
- 首先,我们可以很容易想到拿一个前缀数组去保存AB的数量差,我们这里设A为正,B为负,得到一个prefix_sum数组,prefix_sum[i]=0即代表s到si的子串中A、B数量相等。
- 对于前缀数组prefix_sum,它可以令我们知道哪些子串是AB数量相等的,具体怎么实现,就是从暴力开始,最后发现其有一定的贪心性质,然后利用一个map实现优化,当然直接一个数组也行,但其下标有正有负所以需要做一些处理,我这里就直接map了。具体看代码注释。
- 知道了哪些子串AB数量相等后,我们还要知道连续A子串和连续B子串的数据,根据题意得知最后要求的是最长的字典序不递减的子串的长度,所以可以设置一个preA数组和sufB数组分别表示以s[i]为末尾的连续A子串长度和以s[i]为开头的连续B子串长度。
源码与注释:
#include<iostream>
#include<map>
#include<algorithm>
using namespace std;
const int N = 2e5 + 10;
map<int, int> M; //M[k]存放字符串s中前缀和为k的最后下标i, 即最大的i使s[1]-- - s[i]的代数和为k
char s[N];
int n;//字符串长度<=200000
int prefix_sum[N];//以A为正,B为负,存放前缀和,和为0即代表A、B数量相等
int preA[N];//preA[i]表示以s[i]为末尾的连续A子串长度
int sufB[N];//sufB[i]表示以s[i]为开头的连续B子串长度
//preA和sufB的前后缀性质是由题目中最终要求的 字典序不递减 决定的。
int main()
{cin >> n >> s + 1;//求前缀和prefix_sumfor (int i = 1; i <= n; i++) {if (s[i] == 'A' ) prefix_sum[i] = prefix_sum[i - 1] + 1;else prefix_sum[i] = prefix_sum[i - 1] - 1;}//求preA和sufB以获得连续子串的数据for (int i = 1, j = n; i <= n; i++, j--) {if (s[i] == 'A')preA[i] = preA[i - 1] + 1;if (s[j] == 'B')sufB[j] = sufB[j + 1] + 1;}//求出sufB和preA后,按照暴力的思想可以像下面这样遍历,但无奈n的规模有200000,显然是不行的//int MAX = -1;//for (int i = 0; i <= n; i++) {// for (int j = i + 2; j <= n; j++) {// if (prefix_sum[j] - prefix_sum[i] == 0) {// MAX = max(MAX, j - i + preA[i] + sufB[j + 1]);// }// }//}//cout << MAX << endl;//以下用一个map M存放前缀和的一些信息以做优化for (int i = n; i >= 1; i--) {if (M[prefix_sum[i]] == 0) {M[prefix_sum[i]] = i;//其中M[k]存放字符串s中前缀和为k的最后下标i,即最大的i使s[1]---s[i]的代数和为k}}//这里有点贪心的思维,即在求M时只看最后的下标//这样一来,我们知道s[1]---s[i]前缀和为prefix_sum[i],则最长的前缀和为k的子串为s[1]---s[ M[prefix_sum[i]] ],//所以有了M,我们就知道以s[i+1]为头的最长的AB数相等的子串为s[i+1]---s[ M[prefix_sum[i]] ],其长度为M[prefix_sum[i]]-i//所以我们也不用去做过多的循环了,一轮贪心选择即可完成int MAX = -1;for (int i = 1; i <= n; i++) {//以s[i+1]为头的最长子串及连接两边AB后的长度。int nowLength = (M[prefix_sum[i]] - i) + (preA[i] + sufB[M[prefix_sum[i]] + 1]);MAX = max(MAX, nowLength);}cout << MAX << endl;return 0;
}
纯源码:
#include<iostream>
#include<map>
#include<algorithm>
using namespace std;
const int N = 2e5 + 10;
map<int, int> M;
char s[N];
int n,prefix_sum[N],preA[N],sufB[N];
int main()
{cin >> n >> s + 1;for (int i = 1; i <= n; i++) {if (s[i] == 'A' ) prefix_sum[i] = prefix_sum[i - 1] + 1;else prefix_sum[i] = prefix_sum[i - 1] - 1;}for (int i = 1, j = n; i <= n; i++, j--) {if (s[i] == 'A')preA[i] = preA[i - 1] + 1;if (s[j] == 'B')sufB[j] = sufB[j + 1] + 1;}for (int i = n; i >= 1; i--) {if (M[prefix_sum[i]] == 0) {M[prefix_sum[i]] = i;}}int MAX = -1;for (int i = 1; i <= n; i++) {int nowLength = (M[prefix_sum[i]] - i) + (preA[i] + sufB[M[prefix_sum[i]] + 1]);MAX = max(MAX, nowLength);}cout << MAX << endl;return 0;
}
结果:
最后贴一张AC图
就酱:)
字符串魔法hard(前后缀与贪心)相关推荐
- 洛谷3613睡觉困难综合征(LCT维护链信息(前后缀)+贪心)
这个题目还是很好啊QWQ很有纪念意义 首先,如果在序列上且是单次询问的话,就是一个非常裸的贪心了QWQ这也是NOI当时原题的问题和数据范围 我们考虑上树的话,应该怎么做? 我的想法是,对于每一位建一个 ...
- Go 学习笔记(51)— Go 标准库之 strings(字符串比较、字符串前后缀、字符串统计、字符串索引、字符串包含、字符串转换、字符串复制、字符串替换、字符串去除、字符串分割和连接)
1. 概述说明 import "strings" strings 包实现了用于操作字符的简单函数. strings 包与 bytes 包中的函数用法基本一样. 2. 主要函数 2. ...
- 字符串——OKR-Periods of Words(kmp求最短相同前后缀或者说求最长循环节)
传送门:OKR-Periods of Words 思路:题目要求的是最大的前缀Q使得A是QQ的前缀,同时Q不能等于A, 比如在bababab,要使得周期最大,应该选的循环节就是bababa, 另一个有 ...
- LeetCode 第 58 场力扣夜喵双周赛(动态规划、马拉车算法,前后缀处理)/ 第 253 场力扣周赛(贪心,LIS)
第 58 场力扣夜喵双周赛 两道600多 5193. 删除字符使字符串变好 题目描述 一个字符串如果没有 三个连续 相同字符,那么它就是一个 好字符串 . 给你一个字符串 s ,请你从 s 删除 最少 ...
- kmp, 字符串相同前后缀
catalog 相同前后缀 O(n)构造 最长前后缀 数组 代码 在kmp中的用处.kmp原理 暴力 优化A_ind 优化B_ind kmp模板 相同前后缀 kmp的本质,就是 相同前后缀 所谓 相同 ...
- `算法知识` 字符串相同前后缀
相同前后缀 对于长度N的字符串, 找到其长度最长的相同前后缀的长度 (且长度需<N) 字符串ababab的最长前后缀为abab; 字符串abcdabc的最长前后缀为abc 这个概念不应该陌生, ...
- kmp算法中字符串前后缀公共长度的总结
kmp算法比较重要的一步骤,需要根据模式串构建next或nextval数组 通过前后缀公共字符串最大长度来进行构建的,前后缀概念是分成2个的,字符串前缀和字符串后缀 字符串前缀的意思是,不包含字符串最 ...
- KMP----next数组 最长相同前后缀 递归求法解释
理解递归(推)求解next数组的代码是个难点,对于刚入门来说 next数组求解的时候是 已知next[0....j],next[j]=k.求解next[j+1] 首先next[j]=k的含义是说前j- ...
- HDU 4763 Theme Section(KMP+枚举公共前后缀)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4763 题目大意: 给你一个字符串s,存在一个 子串E同时出现在前缀.中间.后缀,即EAEBE这种模式 ...
最新文章
- Playmaker Input篇教程之Playmaker购买下载和导入
- 灰度图片维度与彩色图片维度-python-scikit-image包
- [转]Laravel 4之URL生成
- linux 记事本程序,Linux记事本操作
- SQL注入(1)--判断是否存在SQL注入漏洞
- Vue学习笔记(二)—— vue项目中使用axios
- inputstream 初始化_如何完美回答面试官问的Mybatis初始化原理!
- asp教室使用_为什么要在教室中使用开放式硬件?
- 华栖云科技图形图像视音频算法岗面试经验
- 微信跳转,wap浏览器跳转到微信
- 解码平安:如何成为世界级综合金融集团
- vue 微信支付的坑_微信支付踩坑
- 攒机笔记二十:改造笔记本电脑(华硕A555L)
- 2021年危险化学品生产单位安全生产管理人员新版试题及危险化学品生产单位安全生产管理人员考试总结
- 【愚公系列】2023年02月 .NET CORE工具案例-Lunar日历转换
- 《风车》——仓央嘉措
- 苹果电池显示维修_安装第三方电池的iPhone也可享受苹果官方维修
- 一款原型设计工具“墨刀”的介绍
- 练习六(归并排序、第k小元素、棋盘覆盖、大整数乘法)
- 中国分省30米DEM(NASA 2020版)