Codeforces Round 934 (Div. 2) ---- D. Non-Palindromic Substring --- 题解

目录

D. Non-Palindromic Substring :

题目描述:

思路解析:

下面给出两种代码的代码实现:

代码一:线段树实现hash判断回文字符串

代码二:manacher判断回文字符串


D. Non-Palindromic Substring :

题目描述:

假设有一个字符串长度为n, 如果这个字符串没有长度为k的回文子串,那么称这个字符串为k好字符串,现在定义f(str) = k1+k2+......,如果字符串str是一个k1字符串,k2字符串......

现在给出一个长度为n的字符串和q次查询,每次查询区间 [li,ri] 问这个区间对应的字符串的f值为多少。

思路解析:

任意一个字符串一定不是1好字符串,因为每个长度为1的子串都是回文串。

假设现在字符串长度为n,k为偶数,什么情况才能满足字符串不是k好字符串 假设k==4

那么字符串有形如 a1a2a3a4a5....的结构 假设 (a1 a2 a3 a4) 和 (a2 a3 a4 a5) 是回文的,那么可以推出a1 == a2 == a3 == a4 == a5,即只有一个字符重复的字符串才可能出现 不是 k好字符串 (k为偶数) 且此时,奇数也不为好字符串。

假设现在字符串长度为n,k为奇数,什么情况才能满足字符串不是k好字符串,假设k==3

那么字符串有形如 a1a2a3a4a5.....的结构 假设(a1a2a3) 和 (a2a3a4) 回文的,那么可以推出 a1 == a3 == a5.... a2 == a4,即只要满足是两个字符循环的字符串 (如ababab...)。可以发现此时任意长度小于等于 n的奇数k, 字符串都不是k好字符串,而且单字符循环可以看作此情况的特殊情况。

那么现在整个查询情况可以分为三类:

(1) 单字符循环的字符串, 此时f值为0

(2) 双字符循环的字符串,此时f值为 2 + 4 + ..... + m  (m <= n),如果n长度为奇数则不加n

(3) 啥也不是 此时f值 2 + 3 + 4 + ..... + n, 如果长度为n的字符串是回文字符串则减去n

则(2)f值可看作 2 + 4 + ... + m (m < n) (3) f值可看作  2 + 3 + ....+ (n-1)  这两种情况都去特判一下整个字符串是否为回文字符串即可。 这里判断字符串是否回文字符串有两种做法,hash或者manacher。

// 这里判断循环字符串可以利用边界判断的方法,详细思路请看代码,自己模拟即可

下面给出两种代码的代码实现:

代码一:线段树实现hash判断回文字符串

import java.io.*;
import java.math.BigInteger;
import java.util.*;public class Main {static int inf = (int) 2e7;static int[] ff = new int[26];static SegTree tree;public static void main(String[] args) throws IOException {pow = new long[MAXN];pow[0] = 1;for (int i = 1; i < MAXN; i++) {pow[i] = pow[i-1] * base % mod;}Random random = new Random();for (int i = 0; i < 26; i++) {ff[i] = random.nextInt(235879);}int t = f.nextInt();tree = new SegTree();while (t > 0) {solve();t--;}w.flush();w.close();br.close();}public static void solve() {n = f.nextInt();int q = f.nextInt();s = (" " + f.next()).toCharArray();TreeSet<Integer> s1 = new TreeSet<>();TreeSet<Integer> s2 = new TreeSet<>(); // 利用s1判断单字符循环, s2判断双字符循环for (int i = 1; i < n; i++) {if (s[i+1] != s[i]) s1.add(i);if (i+2 <= n && s[i] != s[i+2]) s2.add(i);}s1.add(n+1);s2.add(n+1);tree.build(1, 1, n);for (int i = 0; i < q; i++) {int l = f.nextInt();int r = f.nextInt();int len = r - l + 1;long ans = 0;if (l == r) {w.println(0); continue;}int a = s1.ceiling(l);if (a >= r) {w.println(0); continue;}else {a = s2.ceiling(l);if (a >= r - 1) ans = (long) ((len - 1) / 2) * ((len - 1) / 2 + 1);else ans = (long) len * (len - 1) / 2 - 1;}long[] b = tree.qry(1, l, r);if (b[0] != b[1]) ans += len;w.println(ans);}}static int base = 29;static int mod = (int) 1e9 + 9;static long[] pow;static int MAXN = (int) 2e5 + 5;static char[] s;static int n;public static class Node{int l,r;long[] sum = new long[2];}public static class SegTree{Node[] t = new Node[MAXN * 4];public SegTree(){for (int i = 0; i < MAXN * 4; i++) {t[i] = new Node();}}public void build(int root, int l, int r){t[root].l = l;t[root].r=r;if (t[root].l == t[root].r){t[root].sum[0] = ff[s[l] - 'a'];t[root].sum[1] = ff[s[l] - 'a'];return;}int ch = root << 1;int mid = (l + r) >> 1;build(ch, l, mid); build(ch|1, mid+1, r);update(root);}void update(int root){int ch = root << 1;int len1 = t[ch|1].r - t[ch|1].l + 1;int len2 = t[ch].r - t[ch].l + 1;t[root].sum[0] = (t[ch].sum[0] * pow[len1] % mod + t[ch|1].sum[0]) % mod;t[root].sum[1] = (t[ch].sum[1] + t[ch|1].sum[1] * pow[len2] % mod) % mod;}long[] qry(int root, int l, int r){if (t[root].l == l && t[root].r == r){return t[root].sum;}int ch = root << 1; int mid = (t[root].l + t[root].r) >> 1;if (r <= mid) return qry(ch, l, r);else if (l > mid) return qry(ch|1, l, r);else {long[] a = qry(ch, l, mid);long[] b = qry(ch|1, mid+1, r);long[] tmp = new long[2];int len1 = r - mid;int len2 = mid - l + 1;tmp[0] = (a[0] * pow[len1] % mod + b[0]) % mod;tmp[1] = (a[1] + b[1] * pow[len2] % mod) % mod;return tmp;}}}static PrintWriter w = new PrintWriter(new OutputStreamWriter(System.out));static Input f = new Input(System.in);static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));static class Input {public BufferedReader reader;public StringTokenizer tokenizer;public Input(InputStream stream) {reader = new BufferedReader(new InputStreamReader(stream), 32768);tokenizer = null;}public String next() {while (tokenizer == null || !tokenizer.hasMoreTokens()) {try {tokenizer = new StringTokenizer(reader.readLine());} catch (IOException e) {throw new RuntimeException(e);}}return tokenizer.nextToken();}public String nextLine() {String str = null;try {str = reader.readLine();} catch (IOException e) {// TODO 自动生成的 catch 块e.printStackTrace();}return str;}public int nextInt() {return Integer.parseInt(next());}public long nextLong() {return Long.parseLong(next());}public Double nextDouble() {return Double.parseDouble(next());}public BigInteger nextBigInteger() {return new BigInteger(next());}}
}

代码二:manacher判断回文字符串

import java.io.*;
import java.math.BigInteger;
import java.util.*;public class Main {static int inf = (int) 2e7;static int[] ff = new int[26];public static void main(String[] args) throws IOException {Random random = new Random();for (int i = 0; i < 26; i++) {ff[i] = random.nextInt(235879);}int t = f.nextInt();while (t > 0) {solve();t--;}w.flush();w.close();br.close();}public static void solve() {int n = f.nextInt();int q = f.nextInt();String str = f.next();char[] s = (" " + str).toCharArray();TreeSet<Integer> s1 = new TreeSet<>();TreeSet<Integer> s2 = new TreeSet<>();for (int i = 1; i < n; i++) {if (s[i+1] != s[i]) s1.add(i);if (i+2 <= n && s[i] != s[i+2]) s2.add(i);}s1.add(n+1);s2.add(n+1);int[] p = manacher(str.toCharArray());for (int i = 0; i < q; i++) {int l = f.nextInt();int r = f.nextInt();int len = r - l + 1;long ans = 0;if (l == r) {w.println(0); continue;}int a = s1.ceiling(l);if (a >= r) {w.println(0); continue;}else {a = s2.ceiling(l);if (a >= r - 1) ans = (long) ((len - 1) / 2) * ((len - 1) / 2 + 1);else ans = (long) len * (len - 1) / 2 - 1;}if (p[l + r - 1] < len) ans += len;w.println(ans);}}public static int[] manacher(char[] s){int n = s.length;char[] a = new char[2 * n + 1];for (int i = 0; i < n; i++) {a[2 * i] = '#';a[2 * i + 1] = s[i];}a[2 * n] = '#';return manacher_odd(a);}public static int[] manacher_odd(char[] s){int len = 0;int n = s.length;int[] p = new int[n];int r = 0;int c = 0;for (int i = 0; i < n; i++) {len = r > i ? Math.min(p[2 * c - i], r - i) : 1;while (len + i < n && i - len >= 0 && s[i + len] == s[i - len]) len++;if (len + i > r){c = i;r = len + i;}p[i] = len;}for (int i = 0; i < n; i++) {p[i]--;}return p;}static PrintWriter w = new PrintWriter(new OutputStreamWriter(System.out));static Input f = new Input(System.in);static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));static class Input {public BufferedReader reader;public StringTokenizer tokenizer;public Input(InputStream stream) {reader = new BufferedReader(new InputStreamReader(stream), 32768);tokenizer = null;}public String next() {while (tokenizer == null || !tokenizer.hasMoreTokens()) {try {tokenizer = new StringTokenizer(reader.readLine());} catch (IOException e) {throw new RuntimeException(e);}}return tokenizer.nextToken();}public String nextLine() {String str = null;try {str = reader.readLine();} catch (IOException e) {// TODO 自动生成的 catch 块e.printStackTrace();}return str;}public int nextInt() {return Integer.parseInt(next());}public long nextLong() {return Long.parseLong(next());}public Double nextDouble() {return Double.parseDouble(next());}public BigInteger nextBigInteger() {return new BigInteger(next());}}
}

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

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

相关文章

大数据Hadoop生态圈体系视频课程

课程介绍 熟悉大数据概念&#xff0c;明确大数据职位都有哪些&#xff1b;熟悉Hadoop生态系统都有哪些组件&#xff1b;学习Hadoop生态环境架构&#xff0c;了解分布式集群优势&#xff1b;动手操作Hbase的例子&#xff0c;成功部署伪分布式集群&#xff1b;动手Hadoop安装和配…

codeforces div4 Double Strings

#include<iostream> #include<algorithm> #include<cstring> #include<map> using namespace std; int T, n; string s[900005]; map<string, int>mm;//存放每一个字符串是否出现过 int main() {cin >> T;while (T--){mm.clear();//每次清…

服务端测试开发必备技能:Mock测试

什么是mock测试 Mock 测试就是在测试活动中&#xff0c;对于某些不容易构造或者不容易获取的数据/场景&#xff0c;用一个Mock对象来创建以便测试的测试方法。 Mock测试常见场景 无法控制第三方系统接口的返回&#xff0c;返回的数据不满足要求依赖的接口还未开发完成&#…

linux 离线安装 dotnet tool

1. 在官网下载对应的nuget包,比如: dotnet-dump NuGet Gallery | dotnet-dump 3.1.57502 注意文件名称: dotnet-dump.3.1.57502.nupkg 我犯了一个错误,下载比较慢,然后通过迅雷来下载,结果没有后缀名称. 2. 然后拷贝到linux上,比如: 拷贝到dp文件夹下, 在dp文件夹上级执行命…

2965: 寻宝猎人(贪心)

2965: 寻宝猎人 题目描述 寻宝猎人Tom发现了一处宝藏&#xff0c;宝藏为一个N * M 的矩阵组成&#xff0c;矩阵的每一个点都包含一个钱袋&#xff0c;钱袋中装有若干金币。现在Tom只想从这个矩阵中拿走一块 3 * 3 的矩阵&#xff0c;请问他能拿走的最大金币数量。 输入 第一行输…

mfc140.dll丢失的解决方法,快速修复win10系统dll问题

在Windows 10操作系统环境下&#xff0c;如果发现系统中关键的动态链接库文件mfc140.dll丢失&#xff0c;可能会引发一系列运行问题。mfc140.dll是Microsoft Foundation Class Library&#xff08;微软基础类库&#xff09;的重要组成部分&#xff0c;对于许多基于该库开发的应…

ACL访问控制协议

ACL 1. Access Control List 2. ACL是一种包过滤技术。 3. ACL基于IP包头的IP地址、四层TCP/UDP头部的端口号、[5层数据] 基于三层和四层过滤 4. ACL在路由器上配置&#xff0c;也可以在防火墙上配置&#xff08;一般称为策略&#xff09; 5. ACL主要分为2大类&…

代码随想录算法训练营第三十五天|860. 柠檬水找零,406. 根据身高重建队列,452. 用最少数量的箭引爆气球

860. 柠檬水找零 题目 在柠檬水摊上&#xff0c;每一杯柠檬水的售价为 5 美元。顾客排队购买你的产品&#xff0c;&#xff08;按账单 bills 支付的顺序&#xff09;一次购买一杯。 每位顾客只买一杯柠檬水&#xff0c;然后向你付 5 美元、10 美元或 20 美元。你必须给每个顾…

【干货】无源滤波器设计讲解,工作原理+设计步骤

今天给大家分享的是&#xff1a;无源模拟滤波器针对很多入门小白不懂滤波器设计&#xff0c;一些老工程师上班很多年有的也不懂得总结知识点&#xff0c;以及想学习不知道怎么系统学习的这一类人群&#xff0c;前方知识点来袭&#xff0c;请君放心食用~ 在信号处理领域&#x…

java的一些内部小知识,类与对象的关系

目录 1. java2. 类与对象的关系 1. java test.java ---- javac --> Test.class ---- java-----> 内存 ----> cpu 源文件 二进制代码 所有正在运行的软件都在内存中有自己的内存空间 jvm —>运行java程序的&#xff0c;java虚拟机 main(); // 内部调用run()run(i…

苍穹外卖项目笔记

软件开发流程 需求分析&#xff1a;说明书和原型 设计&#xff1a;UI&#xff0c;数据库&#xff0c;接口设计 编码&#xff1a;项目代码&#xff0c;单元测试 测试&#xff1a;测试用例&#xff0c;测试报告 上线运维&#xff1a;软件环境安装&#xff0c;配置 软件环境…

迷宫与陷阱(蓝桥杯)

文章目录 迷宫与陷阱问题描述bfs解题思路代码 迷宫与陷阱 问题描述 小明在玩一款迷宫游戏&#xff0c;在游戏中他要控制自己的角色离开一间由 N x N 个格子组成的2D迷宫。 小明的起始位置在左上角&#xff0c;他需要到达右下角的格子才能离开迷宫&#xff0c;每一步&#xf…

Mybatis中条件传入多个参数时,如何处理

entity&#xff1a; Data AllArgsConstructor NoArgsConstructor public class User {private Integer id;private String username;private String password;private String phone;private String address; }dao接口&#xff1a; public interface UserDAO {List<User>…

C++ 如何去认识模板

引言: C模板是泛型编程的基石,允许程序员定义可与任何数据类型协作的函数和类。这种机制极大地增加了代码的灵活性和复用性,是C最强大的特性之一。本文将深入探讨C模板的概念、优势以及使用方法,帮助读者掌握这一重要的编程工具。 文章目录 模板简介模板的优势一、模板基础1.1…

基于vue+element+springboot+uniapp开发的智慧城管源码,java智慧城市管理综合执法系统源码

智慧城管源码&#xff0c;智慧执法&#xff0c;数字化城市管理综合执法系统源码 智慧城管系统充分利用物联网、云计算、信息融合、网络通讯、数据分析与挖掘等技术&#xff0c;对城市管理进行全方位覆盖。它通过建立城市综合管理平台&#xff0c;将城市的信息和管理资源有机结合…

Qt_day5:2024/3/26

作业&#xff1a;实现闹钟 代码&#xff1a; 头文件&#xff1a; #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QTimerEvent> //定时器事件 #include <QTime> //时间类 #include <QtTextToSpeech> //文本转语音类 #include <…

hgvs中的[数字]是什么意思

hgvs中的[数字],例如NM_144670.6(A2ML1):c.462+9GGA[5]中的[5]详细解释: Repeated Sequences# Repeated sequence: a sequence where, compared to a reference sequence, a segment of one or more nucleotides (the repeat unit) is present several times, one after the…

错误 LNK1104 无法打开文件“mfc140.lib”

如图&#xff0c;编译一个别人已有的项目&#xff0c;我的编译报错为&#xff1a; 但是我所有文件夹全局搜索了一下&#xff0c;这个文件是存在的。但是当前项目访问不到。 更改方法&#xff1a;项目->属性->配置属性->VC目录->库目录 全局搜索找到mfc140.lib的…

【LeetCode 算法专题突破】定长滑动窗口

文章目录 前言[1456. 定长子串中元音的最大数目](https://leetcode.cn/problems/maximum-number-of-vowels-in-a-substring-of-given-length/)题目描述&#xff1a;难度分1263代码与解题思路代码复盘 [2269. 找到一个数字的 K 美丽值](https://leetcode.cn/problems/find-the-k…

如何在pycharm中使用anaconda的虚拟环境

https://blog.csdn.net/weixin_43486940/article/details/123229290