字符串思维题练习 DAY6 (CF 245H , CF 559B , CF 1731C , CF1109B)

字符串思维题练习 DAY6 (CF 245H , CF 559B , CF 1731C , CF1109B)

CF 245 H. Queries for Number of Palindromes(字符串 + dp)

Problem - H - Codeforces

大意:给出一个字符串S (|S| ≤ 5000) , 给出 Q 次询问 , 每次询问 S 的一个区间 [l , r] , 求区间字符串的回文子串个数。

思路:一开始考虑了 马拉车 ,求出每个位置作为回文中心的最大回文半径 , 但是这样的话每次询问都要遍历区间[l , r] 去更新每一个回文中心所对应的回文半径 , 复杂度

O ( ∑ i = 1 Q ( r i − l i ) ) O(\sum_{i=1}^{Q}(r_i-l_i) ) O(i=1Q(rili))

显然是不能接受的 , 考虑 O(N^2) 预处理 , O(1) 回答询问

a n s [ i ] [ j ] 为 [ l , r ] 的答案 ans[i][j] ~为[l , r]的答案 ans[i][j] [l,r]的答案

考虑转移

a n s [ l ] [ r ] = a n s [ l ] [ r − 1 ] + p r e [ l ] [ r ] ans[l][r]=ans[l][r-1]+pre[l][r] ans[l][r]=ans[l][r1]+pre[l][r]

pre[l][r] 是右边界为 r , 左边界 ≥ l 所有字符串中回文串的个数

p r e [ l ] [ r ] = p r e [ l ] [ r − 1 ] + d p [ l ] [ r ] pre[l][r] = pre[l][r-1]+dp[l][r] pre[l][r]=pre[l][r1]+dp[l][r]

dp[l][r] 为 [l , r] 这个区间的字符串是否为回文串

所以显而易见问题就变成了就 dp[l][r] , 有两种求法

第一种 : 区间dp

不难看出我们要求的是一个个区间 , 且区间之间存在转移关系 , 所以可以使用区间 dp 进行转移。

初始化:初始化奇回文和偶回文 , 显然所有长度为一的区间都为回文区间 , 长度为二的区间判断是否回文即可。

转移方程: d p [ l ] [ r ] ∣ = ( d p [ l + 1 ] [ r − 1 ] & & ( s [ l ] = = s [ r ] ) ) 转移方程:dp[l][r] |= (dp[l + 1][r - 1] ~~\&\&~~ (s[l] == s[r])) 转移方程:dp[l][r]=(dp[l+1][r1]  &&  (s[l]==s[r]))

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
//#define int long long
const int INF = 9e18;
const int N = 5e3 + 10;
const int mod = 1e9 + 7;
typedef pair<int,int>PII;int ans[N][N] , pre[N][N];
bool dp[N][N];
int n , q;
string s;signed main(){IOScin >> s;n = s.size();s = '?' + s;for(int i = 1 ; i <= n ; i ++) dp[i][i] = 1;for(int i = 1 ; i < n ; i ++) dp[i][i + 1] = (s[i] == s[i + 1]);for(int len = 3 ; len <= n ; len ++) {for(int l = 1 ; l <= n ; l ++) {int r = l + len - 1;dp[l][r] |= (dp[l + 1][r - 1] && (s[l] == s[r]));}}for(int r = 1 ; r <= n ; r ++) {for(int l = r ; l >= 1 ; l --){pre[l][r] = pre[l + 1][r] + dp[l][r];}}for(int l = 1 ; l <= n ; l ++) {for(int r = l ; r <= n ; r ++) {ans[l][r] = ans[l][r - 1] + pre[l][r];}}cin >> q;while(q --) {int l , r;cin >> l >> r;cout << ans[l][r] << "\n";}return 0;
}
//freopen("文件名.in","r",stdin);
//freopen("文件名.out","w",stdout);

第二种:马拉车

马拉车的思路比较直接 , 求出每个回文中心对应的回文半径的长度 , 以当前回文中心更新即可。

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
//#define int long long
//const int INF = 9e18;
const int N = 5e3 + 10;
const int mod = 1e9 + 7;
typedef pair<int,int>PII;int ans[N][N] , pre[N][N];
bool dp[N][N];
int n , q , m;
string s , t;int d[N * 2 + 1];
//给出一个字符串求d[i]数组并返回马拉车串
string manacher(string s){string now = "#$";int n = s.size();for(int i = 0 ; i < n ; i ++) now += s[i] , now += '$';n = now.size();d[1] = 1;for(int i = 2 , l , r = 1; i < n ; i ++){if(i <= r) d[i] = min(d[r - i + l] , r - i + 1);else d[i] = 1;while(now[i - d[i]] == now[i + d[i]]) d[i] += 1;if(i + d[i] - 1 > r) l = i - d[i] + 1 , r = i + d[i] - 1; }return now;	
}void watch(string s){int n = s.size();for(int i = 0 ; i < n ; i ++) cout << s[i] << " ";cout << "\n"; for(int i = 0 ; i < n ; i ++) cout << d[i] << " ";cout << "\n";
}signed main(){IOScin >> s;n = s.size();t = manacher(s);m = t.size();
//	watch(s);	int len = 0 , l = 0 , r = 0;for(int i = 1 ; i <= m ; i ++) {if(i & 1) {//偶回文中心len = (d[i] - 1) / 2;l = (i - 1) / 2;r = (i + 1) / 2;} else {len = d[i] / 2;l = r = i / 2;}for(int i = 1 ; i <= len ; i ++ , l -= 1 , r += 1) {dp[l][r] = 1;}}for(int r = 1 ; r <= n ; r ++) {for(int l = r ; l >= 1 ; l --){pre[l][r] = pre[l + 1][r] + dp[l][r];}}for(int l = 1 ; l <= n ; l ++) {for(int r = l ; r <= n ; r ++) {ans[l][r] = ans[l][r - 1] + pre[l][r];}}cin >> q;while(q --) {int l , r;cin >> l >> r;cout << ans[l][r] << "\n";}return 0;
}
//freopen("文件名.in","r",stdin);
//freopen("文件名.out","w",stdout);

CF 559 B. Equivalent Strings(哈希+搜索剪枝)

Problem - B - Codeforces

大意:两个等长的字符串 a , b(条件相等)需要满足以下两个条件其一:

1 : 两个字符串相等

2: 字符串 a 可以分为等长的 a1 , a2 , 字符串 b 可以分为等长的 b1 b2 。满足 a1 与 b1(条件相等)a2 与 b2(条件相等)或者 a1 与 b2 (条件相等) a2 与 b1 (条件相等)。

给出两个登场字符串判断是否条件相等。

思路:不难看出这个条件相等是一个递归的定义 , 考虑递归搜索,哈希比较区间字符串。不妨计算一下递归搜索的复杂度。

首先考虑搜索的深度 , 由于每次往下走一层区间的长度减半 , 所以最多搜索 log(2e5) = 18 层 , 每次搜索 , 每个状态会分裂为四个状态即比较(a1 , b1) (a2 , b2) (a1 , b2) (a2 , b1) , 比较的次数为 4^18 = 6e15 , 非常恐怖的复杂度。

考虑搜索剪枝:

剪枝1 : 两个条件相等的区间字符的种类数和每种的个数相等 , 考虑前缀和处理 , O(1) 查询区间的字符个数 , 每次搜索之前判断一下是否相等。

剪枝2:对于每一层 , 满足两个条件其中一个当前区间的字符串即为条件相等 , 不用再去搜另外一颗子树。

加上两个剪枝后实测能跑 900ms , 时限 2s

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define int long long
const int INF = 9e18;
const int N = 2e6 + 10;
const int mod = 1e9 + 7;
typedef pair<int,int>PII;#define ull unsigned long long
const int Base = 131;
ull base[N] , hx[N] , hy[N];
string x , y;
int n;
int cntx[N][2] , cnty[N][2];
//-------------------------------------------------------------
//求[l , r) 的散列值 (从 0 开始) 
inline ull get_x(int l,int r){return hx[r] - hx[l] * base[r - l];
}
inline ull get_y(int l,int r){return hy[r] - hy[l] * base[r - l];
}bool ask(int lx , int rx , int ly , int ry) {lx += 1;ly += 1;rx += 1;ry += 1;return (cntx[rx][0] - cntx[lx - 1][0] != cnty[ry][0] - cnty[ly - 1][0]) || (cntx[rx][1] - cntx[lx - 1][1] != cnty[ry][1] - cnty[ly - 1][1]);
}/*
哈希 + 递归搜索剪枝
两次剪枝
*/bool judge(int lx , int rx , int ly , int ry) {if(get_x(lx , rx + 1) == get_y(ly , ry + 1)) return 1;else {int len = rx - lx + 1;if(len & 1) {return 0;} else {int mid = len / 2;bool tag1 = 0 ,  tag2 = 0;if(ask(lx , lx + mid - 1 , ly , ly + mid - 1) || ask(lx + mid , rx , ly + mid , ry)) tag1 = 0;else tag1 = (judge(lx , lx + mid - 1 , ly , ly + mid - 1) && judge(lx + mid , rx , ly + mid , ry));if(tag1) return 1;if(ask(lx , lx + mid - 1 , ly + mid , ry) || ask(lx + mid , rx , ly , ly + mid - 1)) tag2 = 0;else tag2 = (judge(lx , lx + mid - 1 , ly + mid , ry) && judge(lx + mid , rx , ly , ly + mid - 1));if(tag2) return 1;return 0;}}
}signed main(){cin >> x >> y;n = x.size();base[0] = 1;for(int i = 1 ; i <= n ; i ++) base[i] = base[i - 1] * Base;hx[0] = 0;for(int i = 1 ; i <= n ; i ++) {hx[i] = hx[i - 1] * Base + x[i - 1];cntx[i][0] = cntx[i - 1][0] + (x[i - 1] == 'a');cntx[i][1] = cntx[i - 1][1] + (x[i - 1] == 'b');}hy[0] = 0;for(int i = 1 ; i <= n ; i ++) {hy[i] = hy[i - 1] * Base + y[i - 1];cnty[i][0] = cnty[i - 1][0] + (y[i - 1] == 'a');cnty[i][1] = cnty[i - 1][1] + (y[i - 1] == 'b');}if(judge(0 , n - 1 , 0 , n - 1)) {cout << "YES\n";} else {cout << "NO\n";}return 0;
}
//freopen("文件名.in","r",stdin);
//freopen("文件名.out","w",stdout);

CF 1731 C. Even Subarrays(枚举剪枝)

Problem - C - Codeforces

大意:给出一个序列 , 求有多少个子区间异或和不为平方数。

转化问题 , 原题 = 总子区间个数 - 异或和为平方数的子区间个数 , 所以要求异或和为平方数的子区间个数。

思路:显然区间异或和能组成的平方数是有限的 , 最多有 根号个的 , 所以我们不妨对于每一个右边界记录合法的左边界的个数 , 合法的左边界即枚举每一个可能组成的平方数 ,根据 pre[l - 1] = pre[r] ^ x , 求出合法的左边界的前缀状态 , 计数即可。

复杂度 O ( n n ) 复杂度O(n\sqrt n) 复杂度O(nn )

注意:坑点在于异或和能表示的范围和状态记录的范围数组开的大小 , 要注意。

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define int long long
const int INF = 9e18;
const int N = 2e5 + 10;
const int mod = 1e9 + 7;
typedef pair<int,int>PII;/*
ans = all - 区间异或值为平方数的区间个数
*/int n , t , a[N];
int v[N] , cnt;signed main(){IOScin >> t;while(t --) {cin >> n;for(int i = 1 ; i <= n ; i ++) {cin >> a[i];}cnt = 0;v[++cnt] = 0;for(int i = 1 ; i * i <= 2 * n ; i ++) v[++cnt] = i * i;//注意思考这里的空间为什么开四倍vector<int>pre(4 * n + 1);int res = 0 , ans = (n + 1) * n / 2 , now = 0;pre[0] = 1;for(int i = 1 ; i <= n ; i ++) {now ^= a[i];for(int j = 1 ; j <= cnt ; j ++) {res += pre[now ^ v[j]];}			pre[now] += 1;}cout << ans - res << "\n";}return 0;
}
//freopen("文件名.in","r",stdin);
//freopen("文件名.out","w",stdout);

CF 1109 B. Sasha and One More Name(思维)

Problem - B - Codeforces

大意:给出一个回文字符串 , 求最小的分割次数 k , 将当前回文串分割为 k + 1 部分 , 然后重排这 k + 1 部分 , 能得到一个新的回文字符串。

思路:考虑当前字符串是否存在的一个长度 ≤ len / 2 的前缀位置不是当前字符串的border , 如果存在 , 显然 k = 2 的花费就能解决 , 如果不存在 , 手模一下发现不可能存在答案。

对于比 k = 2 更优的答案即 k = 1 的情况 , 考虑暴力枚举分割位置 , 检验方案是否合理 , 复杂度O(n^2);

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define int long long
const int INF = 9e18;
const int N = 2e6 + 10;
const int mod = 1e9 + 7;
typedef pair<int,int>PII;int nex[N];void init(string s){int len = s.size();nex[1] = 0;for(int i = 2 ; i <= len ; i ++){nex[i] = nex[i-1];while(nex[i] && s[nex[i]] != s[i-1]) nex[i] = nex[nex[i]];nex[i] += (s[i-1] == s[nex[i]]);}
}string s;
int n;signed main(){cin >> s;n = s.size();init(s);bool ok = 0;int ans = -1;vector<bool>tag(n + 1);int now = nex[n];while(now) {tag[now] = 1;now = nex[now];}string now_s , now_k;for(int i = 1 ; i < n ; i ++) {now_s = s.substr(i) + s.substr(0 , i);if(now_s == s) continue;now_k = now_s;reverse(now_k.begin() , now_k.end());if(now_s != now_k) continue;ok = 1; }if(ok == 1) {ans = 1;} else {for(int i = 1 ; i <= n / 2 ; i ++) if(!tag[i]) ans = 2;}if(ans == -1) {cout << "Impossible\n";} else {cout << ans << "\n";}return 0;
}
//freopen("文件名.in","r",stdin);
//freopen("文件名.out","w",stdout);

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

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

相关文章

参数解析(牛客)

目录 一、题目 二、代码 一、题目 二、代码 #include <iostream> #include <vector> using namespace std;int main() {string s;getline(cin, s);int i 0;vector<string>ret;while (i < s.size()){if (s[i] )//遇到空格直接跳过{i;}else if (s[i] …

Fbank及MFCC学习

Fbank&#xff1a;FilterBank&#xff1a;人耳对声音频谱的响应是非线性的&#xff0c;Fbank就是一种前端处理算法&#xff0c;以类似于人耳的方式对音频进行处理&#xff0c;可以提高语音识别的性能。获得语音信号的fbank特征的一般步骤是&#xff1a;预加重、分帧、加窗、短时…

day14I102.二叉树的层序遍历

1、102.二叉树的层序遍历 题目链接&#xff1a;https://leetcode.cn/problems/binary-tree-level-order-traversal/ 文章链接&#xff1a;https://programmercarl.com/0102.%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E5%B1%82%E5%BA%8F%E9%81%8D%E5%8E%86.html#%E7%AE%97%E6%B3%95…

详细教程:Postman 怎么调试 WebSocket

WebSocket 是一个支持双向通信的网络协议&#xff0c;它在实时性和效率方面具有很大的优势。Postman 是一个流行的 API 开发工具&#xff0c;它提供了许多功能来测试和调试 RESTful API 接口&#xff0c;最新的版本也支持 WebSocket 接口的调试。想要学习更多关于 Postman 的知…

PDE数值解中,为什么要引入弱解(weak solution)的概念?

See https://www.zhihu.com/question/24243246?utm_sourceqq&utm_mediumsocial&utm_oi1315073218793488384

[Python]黑色背景白色块滑动视频

黑色背景白色块滑动视频&#xff0c;单帧效果如下&#xff1a; 配置参数 1920 1080 400 400 300 60 1920x1080.avi import numpy as np import cv2 as cv import os import syswidth 1920 height 1080 rect_szx 400 rect_szy 300 sz_y_init 400 fps 24width int(sys.a…

十进制小数 与 二进制小数 互转

1、十进制小数 转 二进制小数 公式 小数 * 2得到n1, 将n1的整数作为二进制数第一位&#xff1b;n1的小数 * 2得到n2, 将n2的整数作为二进制数第二位&#xff1b;n2的小数 * 2得到n3, 将n3的整数作为二进制数第三位&#xff1b;… 重复以上步骤&#xff0c;直到小数部分为0或者…

竞赛选题 深度学习+opencv+python实现车道线检测 - 自动驾驶

文章目录 0 前言1 课题背景2 实现效果3 卷积神经网络3.1卷积层3.2 池化层3.3 激活函数&#xff1a;3.4 全连接层3.5 使用tensorflow中keras模块实现卷积神经网络 4 YOLOV56 数据集处理7 模型训练8 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &am…

在服务器上解压.7z文件

1. 更新apt sudo apt-get update2. 安装p7zip sudo apt-get install p7zip-full3. 解压.7z文件 7za x WN18RR.7z

java合成多个pdf为一个pdf

pom文件 <dependency><groupId>com.lowagie</groupId><artifactId>itext</artifactId><version>2.1.7</version></dependency>主文件 import com.lowagie.text.Document; import com.lowagie.text.pdf.PdfCopy; import com.lo…

求三维坐标绕坐标轴旋转后的坐标值

目的 旋转矩阵 应用 沿单个坐标轴旋转 沿多个坐标系旋转 目的 由于其他文章原理介绍比较详细&#xff0c;但应用方面较少。本文直接介绍旋转矩阵的应用&#xff0c;条件为坐标系不变&#xff0c;求旋转后的三维坐标。本文方法较傻瓜式&#xff0c;需要自己进行测试以确认是…

HUAWEI(26)——防火墙双机热备

一、拓扑 二、需求 PC2 ping PC1 FW1与FW2双机热备,FW1为active,FW2为Standby,抢占延时1s VRRP 三、配置 1.IP地址,防火墙接口加入区域 防火墙用户名:admin 防火墙旧密码:Admin@123 防火墙新密码:admin@123 [FW1]interface GigabitEthernet 1/0/0 [FW1-GigabitEthe…

振弦传感器和无线振弦采集仪在隧道安全监测的解决方案

振弦传感器和无线振弦采集仪在隧道安全监测的解决方案 隧道作为交通工程的重要组成部分&#xff0c;具有极高的安全风险&#xff0c;因此隧道安全监测是必不可少的。振弦传感器和无线振弦采集仪作为隧道安全监测的两种重要设备&#xff0c;能够有效地监测隧道的振动情况&#…

elasticsearch(ES)分布式搜索引擎03——(RestClient查询文档,ES旅游案例实战)

目录 3.RestClient查询文档3.1.快速入门3.1.1.发起查询请求3.1.2.解析响应3.1.3.完整代码3.1.4.小结 3.2.match查询3.3.精确查询3.4.布尔查询3.5.排序、分页3.6.高亮3.6.1.高亮请求构建3.6.2.高亮结果解析 4.旅游案例4.1.酒店搜索和分页4.1.1.需求分析4.1.2.定义实体类4.1.3.定…

解决uniapp里scroll-view横向滚动的问题

一、前言 本以为是一件很简单的事&#xff0c;结果浪费了整整一个上午&#xff0c;并且问题并没有全部解决....后来没办法&#xff0c;用了touchmove模拟的滑动&#xff0c;如果有好的解决方法麻烦告诉我...非常感谢~ 一、问题 其实我想要实现的功能很简单&#xff0c;就是一…

微服务、SOA 和 API 之间的区别

在软件开发中&#xff0c;组织的投资方式发生了重大转变&#xff0c;部署了面向架构的方法。这一切都始于 SOA&#xff0c;然后转变为我们称之为微服务的东西。添加到其中的是另一个概念&#xff0c;指定为 API。 在过去的几年里&#xff0c;SOA 和微服务仍然是讨论的话题。随…

【红外双目有监督】CATS系列数据集探索加载器

论文&#xff1a; CATS: A Color and Thermal Stereo Benchmark https://www. flir.com/oem/adas/adas-dataset-form/.Flir thermal dataset 数据集规格 内容 总共 26,442 个 完全注释的帧&#xff0c;以及 15 个不同对象类别的520,000 个 边界框注释。 图片 9,711 张热图像和…

Lazysysadmin靶机

信息收集 主机发现 nmap -sn 192.168.88.0/24 //-sn&#xff1a;制作主机发现&#xff0c;不做端口扫描&#xff1b;扫描结果包含本机IP 端口扫描 nmap --min-rate 10000 -p- 192.168.88.136 扫描端口详细信息 端口扫描发现&#xff0c;该主机的22、80、139、445、3306、…

软件开源快速开发框架:降本增效,助力流程化办公!

随着时代的进步和社会的发展&#xff0c;应用软件开源快速开发框架的优势特点&#xff0c;可以让不少客户朋友顺利实现流程化办公&#xff0c;朝着数字化方向迈进。流辰信息是专业研发低代码技术平台的服务商&#xff0c;一直在低代码平台领域深耕细作&#xff0c;努力钻研&…

合并两个有序数组

给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2&#xff0c;另有两个整数 m 和 n &#xff0c;分别表示 nums1 和 nums2 中的元素数目。 请你 合并 nums2 到 nums1 中&#xff0c;使合并后的数组同样按 非递减顺序 排列。 注意&#xff1a;最终&#xff0c;合并后数组…