[题解] Luogu P5446 [THUPC2018]绿绿和串串
[题解] Luogu P5446 [THUPC2018]绿绿和串串
·题目大意
- 定义一个翻转操作\(f(S_n)\),表示对于一个字符串\(S_n\),
有\(f(S)= \{S_1,S_2,...,S_{n-1},S_n,S_{n-1},...S_2,S_1 \}\)。 - 现在给定一个长度为\(n\)的字符串\(S^{'}\)表示原字符串\(S\)经过若干次(可能为0)旋转之后的一个前缀,
求原来字符串可能的长度\(l\)。 - 显然当\(l > n\)时一定可行,所以只需要输出所有的\(l\leq n\)即可。
\(|S|\leq 10^6,\Sigma |S| \leq 5 \times 10^6\)
·解题思路
首先想到用 \(Manacher\) 。
由于进行翻转操作后回文串长度必定为奇数,所以不用插入字符,然后考虑什么情况下长度是可行的。
- 我们定义一个 \(flag\) 数组,\(flag[i]\) 表示长度为 \(i\) 时是可行的。回文数组为\(p\),\(p[i]\)表示第 \(i\) 位的回文半径位 \(p[i]\)
- 如果只进行了一次翻转操作即可使得前缀为\(S^{'}\),那么有 \(i + p[i] - 1 == n\)
- 如果需要进行\(k\)次翻转才可以使得前缀为\(S^{'}\),那么有 \(i - p[i] + 1 == 1\),然后可以转化为进行\(k - 1\)次的情况。
但是实际操作中我们不用跑 \(k\) 次,只需要倒着跑并记录 \(flag\) ,因为当我们处理长度为 \(i\) 的时候,\(flag[i + 1]\) 到 \(flag[n]\) 都已经处理过了,所以判断 \(flag[i + p[i] - 1] == 1\)即可。 - 时间复杂度为\(O(n)\)。
代码实现
#include <iostream>
#include <cstring>
using namespace std;
#define reg register
namespace io {
char ch[20];
template<typename T>inline void write(T x) {
(x < 0) && (x =- x, putchar('-'));
(x) || putchar('0');
reg int i = 0;
while (x) ch[i++] = x % 10 ^48, x /= 10;
while (i) putchar(ch[--i]);
}
}//快写
#define wt io::write
const int maxN = 1000010;
char s[maxN];
int p[maxN], flag[maxN];
int n;
void work();
int main() {
int t;
scanf("%d", &t);
while (t--) work();
return 0;
}
void work() {
for (reg int i = 1; i <= n; ++i) flag[i] = p[i] = s[i] = 0;
n = 1; s[0] = '@';
scanf("%s", s + 1);
while (s[n]) ++n;
--n;
for (reg int i = 1, r = 0, mid = 0; i <= n; ++i) {
if (i <= r) p[i] = min(p[mid * 2 - i], r - i + 1);
while (s[i + p[i]] == s[i - p[i]]) ++p[i];
if (i + p[i] - 1 >= r) r = i + p[i] - 1, mid = i;
}//Manacher
for (reg int i = n; i; --i) {
if (i + p[i] - 1 == n || (flag[i + p[i] - 1] && i - p[i] + 1 == 1)) flag[i] = 1;
}//上面说的两种情况
for (reg int i = 1; i <= n; ++i)
if (flag[i]) wt(i), putchar(' ');
putchar('\n');
}
[题解] Luogu P5446 [THUPC2018]绿绿和串串的更多相关文章
- 【题解】P5446 [THUPC2018]绿绿和串串(manacher)
[题解]P5446 [THUPC2018]绿绿和串串(manacher) 考虑对于一个串进行\(f\)操作,就是让他变成一个以最后一个节点为回文中心的回文串. 那么对于某个位置\(p\),假如它是一个 ...
- LOJ#6387 「THUPC2018」绿绿与串串 / String (Manacher || hash+二分)
题目描述 绿绿和 Yazid 是好朋友.他们在一起做串串游戏. 我们定义翻转的操作:把一个串以最后一个字符作对称轴进行翻转复制.形式化地描述就是,如果他翻转的串为 RRR,那么他会将前 ∣R∣−1个字 ...
- 洛谷$P5446\ [THUPC2018]$绿绿和串串 $manacher$
正解:$manacher$ 解题报告: 传送门$QwQ$ 考虑这个操作的实质是啥$QwQ$?其实就,变成以最后一个节点为回文中心的回文子串嘛$QwQ$.显然就先跑个马拉车再说呗$QwQ$. 然后接着考 ...
- LOJ6387 [THUPC2018] 绿绿与串串 【manacher】
题目分析: 比较简单,先跑一边manacher,然后对于回文部分可以碰到末尾的一定满足条件,否则向后转移. 代码: #include<bits/stdc++.h> using namesp ...
- loj6387 「THUPC2018」绿绿与串串 / String
还是很好做的,大致就是manacher,每个位置为中心的最长回文串要是能抵到最右边就合法,要是能抵到最左边,那这个点的是否合法取决于以这个点为中心的最长回文串的右端点是否合法. #include &l ...
- 题解 Luogu P2499: [SDOI2012]象棋
关于这道题, 我们可以发现移动顺序不会改变答案, 具体来说, 我们有以下引理成立: 对于一个移动过程中的任意一个移动, 若其到达的位置上有一个棋子, 则该方案要么不能将所有棋子移动到最终位置, 要么可 ...
- 题解 luogu P1144 【最短路计数】
本蒟蒻也来发一次题解第一篇请见谅 这个题有几个要点 1.无向无权图,建图的时候别忘记建来回的有向边[因此WA掉1次 2.无权嘛,那么边长建成1就好了2333333 3.最短路采用迪杰斯特拉(别忘用堆优 ...
- 题解 Luogu P1110 【[ZJOI2007]报表统计】
感谢 @cmy962085349 提供的hack数据,已经改对了. 先声明,我好像是题解里写双$fhq$ $treap$里唯一能过的...(最后两个点啊) 思路:首先看题目,$MIN_GAP_SORT ...
- 题解 Luogu P3370
讲讲这题的几种做法: 暴力匹配法 rt,暴力匹配,即把字符串存起来一位一位判相等 时间复杂度$ O(n^2·m) $ 再看看数据范围 \(n\le10^5,m\le10^3\) 当场爆炸.当然有暴力分 ...
随机推荐
- POJ2482 Stars in Your Window 题解
Fleeting time does not blur my memory of you. Can it really be 4 years since I first saw you? I stil ...
- odoo中接口开发
文章参考:https://blog.csdn.net/qq_33472765/article/details/81913627案例0000001接口调用请求说明:https请求方式:GET(请使用ht ...
- 微信小程序账号注册
想要开发微信小程序,先注册账号申请APPID. 第一步:百度搜索"微信公众平台" 第二步:立即注册 进入注册页面 区别: 订阅号: 订阅号在文件夹里,订阅号消息 一天只能推送一次, ...
- C实现奇偶校验
奇偶校验原理(来自百度百科):奇偶校验(Parity Check)是一种校验代码传输正确性的方法.根据被传输的一组二进制代码的数位中"1"的个数是奇数或偶数来进行校验.采用奇数的称 ...
- js问题记录
1.aixos请求响应302重定向时无法获取返回数据, 解决方法:在请求头中添加 headers: { 'X-Requested-With': 'XMLHttpRequest' },
- npm命令,nrm命令,n命令, nvm命令
npm命令 npm/yarn config set registry https://registry.npm.taobao.org 设置淘宝镜像npm/yarn config get registr ...
- 实现html页面转pdf
实现方式比较简单,使用js代码实现的. 需要引入的js: 1.jQuery.js: 2.html2canvas.js(实现方式是先将Html页面转换成image图片然后在转换为pdf,所以转换之后会有 ...
- 本地Git项目搭建和文件操作
Git项目搭建 git init ---在该文件夹下进入cmd/terminal git clone [url] ---克隆远程仓库到本地 Git文件操作 文件的四种状态: · Untracked:未 ...
- linux笔记2随笔
124.diff命令:文件内容对比 diff命令用于比较多个文本文件之间的差异,这在系统安全防范中非常重要.比如当黑客入侵系统之后,往往会修改一些系统配置文件,从而留下一些后门. 所以作为运维人员.最 ...
- C函数调用(2)
1 //函数调用 2 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <math.h> 6 //根据传入 ...