【CF】团队训练赛2 J-Palindrome Reversion 题解

2024-02-23 05:12

本文主要是介绍【CF】团队训练赛2 J-Palindrome Reversion 题解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

传送门:Palindrome Reversion
标签:字符串

题目大意

规定一个操作:选择字符串中的一段区间[l,r]并使其翻转。现在给出一个字符串s,你要判断能否通过一次操作使其变为回文串。
输入:一个字符串,其长度不超过1e5。
输出:可以则输出l和r,否则输出"-1 -1"。

算法分析

  • 题目的意思可以说是相当的简单,但正所谓大道至简,容易读懂不代表容易做。我们先要知道回文串的特征:翻转后与翻转前完全相同(这里指的是整个字符串reverse)。那么我们可以大胆地猜测一个结论:原字符串首尾相同的部分必然不被包含在操作区间[l,r]中。因为如果有一部分在[l,r]之间,要想保证操作后整个串回文,就要让替换这部分的字符与之相同,那么替换就毫无意义。
  • 也就是说我们可以先通过遍历找到第一个不满足首尾相同的字符,假设其下标是i,这样一来区间[l,r]要么包括i,要么包括len-i+1(这里len为字符串长度)。因为此时的字符串第一个字符和最后一个字符不同,所以需要换掉第一个或者最后一个字符来使得它们相同,但是又要想到同时替换并不会改变它们的对应关系。
  • 所以现在问题变得简单了起来,只要在去掉了首尾相同部分的新字符串上从前往后枚举区间,再从后往前枚举区间,并判断翻转后整体是否回文,就能得出方案的可行性。不过实现起来有点难度,因为要正反各处理一次哈希,还要用到哈希值的截取、拼接等操作,稍有不慎就会出bug。不过有一个小技巧能让本题轻松一半,就是在正向枚举完区间后将整个字符串翻转,然后再次正向枚举区间,这样就和反向枚举区间的作用是一样的了。
  • 最后还要特判一下原字符串本身就回文的情况,这时直接输出1和len即可。只要推出了最初的结论,这题的思路就很简单,难点主要在于实现。以上算法总体时间复杂度为预处理双向哈希的复杂度,即O(n)。

代码实现

#include <iostream>
using namespace std;
#include <algorithm>
#include <cstring>
long long len,hal[100005],har[100005],base[100005]={1LL};
const int mod=1e9+19;
const long long P=13031LL;
char str[100005],str1[100005];
void init(){int i;hal[0]=str[0];for(i=1;i<len;i++)hal[i]=(hal[i-1]*P+str[i])%mod;har[len-1]=str[len-1];for(i=len-2;i>=0;i--)har[i]=(har[i+1]*P+str[i])%mod;
}
long long getl(int l,int r){if(l>r)return 0;if(!l)return hal[r];return (hal[r]-1LL*hal[l-1]*base[r-l+1]%mod+mod)%mod;
}
long long getr(int l,int r){if(l>r)return 0;if(r==len-1)return har[l];return (har[l]-1LL*har[r+1]*base[r-l+1]%mod+mod)%mod;
}
int main(){int i,j,x,len1;bool flag=0;ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);for(i=1;i<=1e5;i++)base[i]=base[i-1]*P%mod;cin>>str1;len1=strlen(str1);for(j=0;j<len1&&str1[j]==str1[len1-j-1];j++);if(j==len1){cout<<1<<' '<<len1;return 0;}for(i=j;i<len1-j;i++)str[i-j]=str1[i];len=len1-2*j;init();x=len/2;for(i=0;i<len;i++)if(i<x){if(getr(x,len-1)==(getr(0,i)*base[x-1+(len&1)-i]%mod+getl(i+1,x-1+(len&1)))%mod){cout<<1+j<<' '<<i+1+j;return 0;}}else{if(getr(i-x+1,i)==(getl(0,i-x-(len&1))+getr(i+1,len-1)*base[i-x-(len&1)+1]%mod)%mod){cout<<1+j<<' '<<i+1+j;return 0;}}reverse(str,str+len);init();x=len/2;for(i=0;i<len;i++)if(i<x){if(getr(x,len-1)==(getr(0,i)*base[x-1+(len&1)-i]%mod+getl(i+1,x-1+(len&1)))%mod){cout<<len1-(i+1+j)+1<<' '<<len1-(1+j)+1;return 0;}}else{if(getr(i-x+1,i)==(getl(0,i-x-(len&1))+getr(i+1,len-1)*base[i-x-(len&1)+1]%mod)%mod){cout<<len1-(i+1+j)+1<<' '<<len1-(1+j)+1;return 0;}}cout<<-1<<' '<<-1;
}

这篇关于【CF】团队训练赛2 J-Palindrome Reversion 题解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/737611

相关文章

cf 164 C 费用流

给你n个任务,k个机器,n个任务的起始时间,持续时间,完成任务的获利 每个机器可以完成任何一项任务,但是同一时刻只能完成一项任务,一旦某台机器在完成某项任务时,直到任务结束,这台机器都不能去做其他任务 最后问你当获利最大时,应该安排那些机器工作,即输出方案 具体建图方法: 新建源汇S T‘ 对任务按照起始时间s按升序排序 拆点: u 向 u'连一条边 容量为 1 费用为 -c,

CF 508C

点击打开链接 import java.util.Arrays;import java.util.Scanner;public class Main {public static void main(String [] args){new Solve().run() ;} }class Solve{int bit[] = new int[608] ;int l

C++ | Leetcode C++题解之第393题UTF-8编码验证

题目: 题解: class Solution {public:static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num &

ural 1297. Palindrome dp

1297. Palindrome Time limit: 1.0 second Memory limit: 64 MB The “U.S. Robots” HQ has just received a rather alarming anonymous letter. It states that the agent from the competing «Robots Unli

C语言 | Leetcode C语言题解之第393题UTF-8编码验证

题目: 题解: static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num & MASK1) == 0) {return

C - Word Ladder题解

C - Word Ladder 题解 解题思路: 先输入两个字符串S 和t 然后在S和T中寻找有多少个字符不同的个数(也就是需要变换多少次) 开始替换时: tips: 字符串下标以0开始 我们定义两个变量a和b,用于记录当前遍历到的字符 首先是判断:如果这时a已经==b了,那么就跳过,不用管; 如果a大于b的话:那么我们就让s中的第i项替换成b,接着就直接输出S就行了。 这样

【秋招笔试】9.07米哈游秋招改编题-三语言题解

🍭 大家好这里是 春秋招笔试突围,一起备战大厂笔试 💻 ACM金牌团队🏅️ | 多次AK大厂笔试 | 大厂实习经历 ✨ 本系列打算持续跟新 春秋招笔试题 👏 感谢大家的订阅➕ 和 喜欢💗 和 手里的小花花🌸 ✨ 笔试合集传送们 -> 🧷春秋招笔试合集 🍒 本专栏已收集 100+ 套笔试题,笔试真题 会在第一时间跟新 🍄 题面描述等均已改编,如果和你笔试题看到的题面描述

LeetCode 第414场周赛个人题解

目录 Q1. 将日期转换为二进制表示 原题链接 思路分析 AC代码 Q2. 范围内整数的最大得分 原题链接 思路分析 AC代码 Q3. 到达数组末尾的最大得分 原题链接 思路分析 AC代码 Q4. 吃掉所有兵需要的最多移动次数 原题链接 思路分析 AC代码 Q1. 将日期转换为二进制表示 原题链接 Q1. 将日期转换为二进制表示 思路分析

Science Robotics 首尔国立大学研究团队推出BBEX外骨骼,实现多维力量支持!

重复性举起物体可能会对脊柱和背部肌肉造成损伤,由此引发的腰椎损伤是工业环境等工作场所中一个普遍且令人关注的问题。为了减轻这类伤害,有研究人员已经研发出在举起任务中为工人提供辅助的背部支撑装置。然而,现有的这类装置通常无法在非对称性的举重过程中提供多维度的力量支持。此外,针对整个人体脊柱的设备安全性验证也一直是一个缺失的环节。 据探索前沿科技边界,传递前沿科技成果的X-robot投稿,来自首尔国立

牛客小白月赛100部分题解

比赛地址:牛客小白月赛100_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ A.ACM中的A题 #include<bits/stdc++.h>using namespace std;#define ll long long#define ull = unsigned long longvoid solve() {ll a,b,c;cin>>a>>b>