P11150 [THUWC 2018] 字胡串

news/2025/10/20 23:19:45/文章来源:https://www.cnblogs.com/Fallinggardenia/p/19153909

P11150 [THUWC 2018] 字胡串

P11150 [THUWC 2018] 字胡串

思路

\(S + T\) 的字典序小于 \(T + S\) 的字典序则称 \(S < T\),若 \(S + T\) 的字典序小于等于 \(T + S\) 的字典序则称 \(S \le T\)

容易注意到如果答案是 \(j\)\(B \le A_{j+1,n}\)
\(\forall 1 \le i \le j\)\(A_{1,i} < B\)。考虑把 \(A\) 划分成 \(T\) 个段 \(S_1, S_2 · · · S_T\) 使得 \(\forall 1 \le i < T, S_i < S_{i+1}\)

显然有多种划分方式,但是我们取 \(|Si|\) 组成的序列字典序最小的。易证对于查询串 \(B\) 一定只会在 \(S_k\)\(S_{k+1}\) 之间插入而不会在 \(S_k\) 内部插入。二分出在哪一段插入,用哈希加二分判 \(B < S_k\) 是否为真即可。

时间复杂度 \(O (q \log n \log (n + m))\)

Code

#include<iostream>
#include<set>
#include<string>
#include<cstring>
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
const int N=1e6+5;
const int base=71;
string str;
bool vis[N];
int n,m,Q,a[N],b[N],tot=0,border[N],father[N],fa_L[N],fa_R[N];
unsigned long long Hash_A[N],Hash_B[N],power[N];
unsigned long long Calc_A(int L,int R)
{return Hash_A[R]-Hash_A[L-1]*power[R-L+1];
}
int Find(int k)
{if(father[k]!=k) return father[k]=Find(father[k]);return k;
}
struct Node
{int L_bound,R_bound;friend bool operator==(Node x,Node y){return x.L_bound==y.L_bound&&x.R_bound==y.R_bound;}friend bool operator<(Node x,Node y){int len=0,pos=0,l=1,r=0,L=0,R=0;len=min(x.R_bound-x.L_bound+1,y.R_bound-y.L_bound+1);if(Calc_A(x.L_bound,x.L_bound+len-1)!=Calc_A(y.L_bound,y.L_bound+len-1)){l=1,r=len,L=x.L_bound,R=y.L_bound;while(l<=r){int Mid=(l+r)>>1;if(Calc_A(L,L+Mid-1)!=Calc_A(R,R+Mid-1))pos=Mid,r=Mid-1;elsel=Mid+1;}return a[L+pos-1]<a[R+pos-1];}if(x.R_bound-x.L_bound==y.R_bound-y.L_bound)return x.L_bound>y.L_bound;if(x.R_bound-x.L_bound>y.R_bound-y.L_bound){if(Calc_A(x.L_bound+len,x.R_bound)==Calc_A(x.L_bound,x.R_bound-len)){if(Calc_A(y.L_bound,y.R_bound)==Calc_A(x.R_bound-y.R_bound+y.L_bound,x.R_bound))return x.L_bound>y.L_bound;l=1,r=y.R_bound-y.L_bound+1,L=y.L_bound,R=x.R_bound-y.R_bound+y.L_bound;while(l<=r){int Mid=(l+r)>>1;if(Calc_A(L,L+Mid-1)!=Calc_A(R,R+Mid-1))pos=Mid,r=Mid-1;elsel=Mid+1;}return a[L+pos-1]<a[R+pos-1];}else{l=1,r=x.R_bound-x.L_bound-len+1,L=x.L_bound+len,R=x.L_bound;while(l<=r){int Mid=(l+r)>>1;if(Calc_A(L,L+Mid-1)!=Calc_A(R,R+Mid-1))pos=Mid,r=Mid-1;elsel=Mid+1;}return a[L+pos-1]<a[R+pos-1];}}else{if(Calc_A(y.L_bound+len,y.R_bound)==Calc_A(y.L_bound,y.R_bound-len)){if(Calc_A(x.L_bound,x.R_bound)==Calc_A(y.R_bound-x.R_bound+x.L_bound,y.R_bound))return y.L_bound<x.L_bound;l=1,r=x.R_bound-x.L_bound+1,L=x.L_bound,R=y.R_bound-x.R_bound+x.L_bound;while(l<=r){int Mid=(l+r)>>1;if(Calc_A(L,L+Mid-1)!=Calc_A(R,R+Mid-1))pos=Mid,r=Mid-1;elsel=Mid+1;}return a[L+pos-1]>a[R+pos-1];}else{l=1,r=y.R_bound-y.L_bound-len+1,L=y.L_bound+len,R=y.L_bound;while(l<=r){int Mid=(l+r)>>1;if(Calc_A(L,L+Mid-1)!=Calc_A(R,R+Mid-1))pos=Mid,r=Mid-1;elsel=Mid+1;}return a[L+pos-1]>a[R+pos-1];}}}
}x;
unsigned long long Calc_B(int L,int R)
{return Hash_B[R]-Hash_B[L-1]*power[R-L+1];
}
bool Check(int L,int R)
{int len=0,pos=0,l=1,r=0;len=min(m,R-L+1);if(Calc_A(L,L+len-1)!=Calc_B(1,len)){l=1,r=len;while(l<=r){int Mid=(l+r)>>1;if(Calc_A(L,L+Mid-1)!=Calc_B(1,Mid))pos=Mid,r=Mid-1;elsel=Mid+1;}return a[L+pos-1]<b[pos];}if(R-L+1==m)return 0;if(R-L+1>m){len=R-L-m+1;if(Calc_A(L+m,R)==Calc_A(L,L+len-1)){if(Calc_B(1,m)==Calc_A(R-m+1,R))return 0;l=1,r=m;while(l<=r){int Mid=(l+r)>>1;if(Calc_B(1,Mid)!=Calc_A(R-m+1,R-m+Mid))pos=Mid,r=Mid-1;elsel=Mid+1;}return b[pos]<a[R-m+pos];}else{l=1,r=R-L+1-m;while(l<=r){int Mid=(l+r)>>1;if(Calc_A(L+m,L+m+Mid-1)!=Calc_A(L,L+Mid-1))pos=Mid,r=Mid-1;elsel=Mid+1;}return a[L+m+pos-1]<a[L+pos-1];}}else{len=m-(R-L+1);if(Calc_B(1,len)==Calc_B(m-len+1,m)){if(Calc_B(len+1,m)==Calc_A(L,R))return 0;l=1,r=R-L+1;while(l<=r){int Mid=(l+r)>>1;if(Calc_B(len+1,len+Mid)!=Calc_A(L,L+Mid-1))pos=Mid,r=Mid-1;elsel=Mid+1;}return b[len+pos]<a[L+pos-1];}else{l=1,r=len;while(l<=r){int Mid=(l+r)>>1;if(Calc_B(1,Mid)!=Calc_B(m-len+1,m-len+Mid))pos=Mid,r=Mid-1;elsel=Mid+1;}return b[pos]<b[m-len+pos];}}
}
set<Node>S;
int main()
{// freopen("string.in","r",stdin);// freopen("string.out","w",stdout);IOS;power[0]=1;for(int i=1;i<N;i++)power[i]=power[i-1]*base;cin>>n>>Q>>str;str=" "+str;for(int i=1;i<=n;i++)a[i]=str[i]-'0',Hash_A[i]=Hash_A[i-1]*base+a[i];for(int i=1;i<=n;i++){x.L_bound=x.R_bound=i;S.insert(x);father[i]=fa_L[i]=fa_R[i]=i;}vis[0]=true;for(int i=1;i<=n;i++){Node tmp=*S.begin();S.erase(S.begin());if(vis[Find(tmp.L_bound-1)]){border[++tot]=tmp.R_bound;vis[Find(tmp.L_bound)]=true;continue;}x.R_bound=tmp.L_bound-1,x.L_bound=fa_L[Find(x.R_bound)];S.erase(x);father[Find(tmp.L_bound)]=Find(x.L_bound);fa_L[Find(tmp.L_bound)]=x.L_bound;fa_R[Find(tmp.R_bound)]=tmp.R_bound;x.R_bound=tmp.R_bound;S.insert(x);}while(Q--){cin>>str;str=" "+str;m=str.size()-1;for(int i=1;i<=m;i++)b[i]=str[i]-'0',Hash_B[i]=Hash_B[i-1]*base+b[i];int L=1,R=tot,pos=0;while(L<=R){int Mid=(L+R)>>1;if(Check(border[Mid-1]+1,border[Mid]))pos=Mid,L=Mid+1;elseR=Mid-1;}cout<<border[pos]<<'\n';}return 0;
}

完结撒花~

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

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

相关文章

newDay13

1.今天课比较多,把作业写写,其他的没干什么 2.明个再学学java什么的 3.没啥问题

微信如何开通wx.getPhoneNumber权限

首先必须是企业认证账号,自己是个人认证账号,折腾了好半天没找到地方。代码测试来测试去都是授权失败。 其次才是按规矩文档配置好 要开通微信小程序的 `wx.getPhoneNumber` 权限(实际上是手机号快速验证组件),需…

日志|JAVAWEB|maven

maven安装步骤配置本地仓库配置阿里云私服系统变量更改idea配置mavenmaven坐标maven加入新依赖

推荐系统与机器学习在会员服务中的应用

本文深入探讨了如何利用机器学习、贝叶斯推荐系统和结构计量经济学等技术,为会员提供个性化服务推荐。内容包括推荐系统架构、多样性优化策略以及动态选择建模等核心技术实现方案。机器学习在会员服务中的科学应用 某…

ManySpeech.MoonshineAsr 使用指南

一、简介 ManySpeech.MoonshineAsr 是 ManySpeech 语音处理套件中一个专门用于moonshine 模型推理的语音识别组件,其使用 c# 开发,底层调用 Microsoft.ML.OnnxRuntime 对 onnx 模型进行解码。具备以下特点:环境兼容…

10.20 —— 2024icpc成都I,B

I. Good Partitions 称位置 \(i\) 为断点,当且仅当 \(a_{i} > a_{i + 1}\)。考虑每个断点的影响:若段长 \(len\) 合法,则 \(a_{i}\) 与 \(a_{i + 1}\) 一定不会在段长为 \(len\) 的划分下出现在同一个段中。那么…

软工第二次编程作业

一、项目介绍项目成员 许潆之3223004863 李思淇3223004861GitHub地址 https://github.com/0919lyski/math_exercise.git这个作业属于哪个课程 https://edu.cnblogs.com/campus/gdgy/Class34Grade23ComputerScience这个…

wqs二分的无脑写法

我曾经被 wqs 二分的边界折磨死了。后面听说有种很无脑的写法,听说是 lhx 大神发明的,记录一下。 假设我们要求的是恰好 \(k\) 个的最大值,大概是这样的: int l = -1e6, r = 1e6; while (l + 1 < r) {int mid =…

2022 ICPC Hangzhou G and 2022 ICPC Jinan

2022 ICPC Hangzhou G and 2022 ICPC Jinan ICPC Hangzhou G 手玩可以发现合法的图中最多只有一个环。所以对于 \(m = n - 1\) 的情况直接判合法;对于 \(m > n\) 的情况直接判非法,此时图中肯定不知有一个环;需要…

C++在类定义内的函数包含static代表什么含义呢?

在类定义内的函数包含static代表什么含义呢? 在类定义内使用 static 关键字修饰成员函数有特殊的含义,它表示这是一个静态成员函数。 静态成员函数的特点 1. 不依赖于类的实例class MyClass { public:static void st…

2025/10/20~2025/?/? 做题笔记 - sb

2025/10/20 AT_arc181_d Prefix Bubble Sort 很显然的有每一次交换都会恰好减少一个逆序对,于是题目转化为每次会产生多少次交换。 那么考虑如何统计交换次数发现当前缀 max 变化时不会产生答案,但是这个折线非常困难…

10-20 Extra-Problem 总结

10-20 Extra-Problem 总结 AtCoder abc280_g 发现点 \((x,y)\) 的距离实际上是 \(\max(|x|,|y|,|x-y|)\)。由于坐标是可平移的,所以 \((x_1,y_1),(x_2,y_2)\) 的距离为 \(\max(|x_1-x_2|,|y_1-y_2|,|(x_1-x_2)-(y_1-y…

Rust 编译加速的最佳实践

Rust 编译慢是“老毛病”,但 2024-2025 年官方和社区集中发力,已经把“等 10 min”级别的大型项目干到了“秒级增量”。下面把当前(2025-10)验证有效的加速手段按“投入-收益”从高到低排序,全部可立刻落地;最后…

ansible底层文件传输机制中默认模式遇到权限拒绝后启用管道模式可以得到解决

为啥我在ansible.cf中加入这一配置后就可以ping通了 [ssh_connection] pipelining = True[student@master ansible]$ ansible all -m ping [WARNING]: sftp transfer mechanism failed on [node2]. Use ANSIBLE_DEBUG…

20232304 2025-2026-1 《网络与系统攻防技术》实验三实验报告

20232304 2025-2026-1 《网络与系统攻防技术》实验三实验报告 1.实验内容 1.1 实验内容 (1)使用msf编码器以及多种格式Payload生成,veil的evasion功能,利用C+Shellcode编程等技巧 (2)通过组合应用各种技术实现恶意代…

10月20日记

1.今天学习java 2.明天学习工程技艺 3.递归的终止条件怎么确定?会不会栈溢出?

笔记本 光驱 的内部结构及用法: 应急强大的系统启动 (恢复) 光盘 (DVD+R/RW)

笔记本 光驱 的内部结构及用法: 应急强大的系统启动 (恢复) 光盘 (DVD+R/RW)pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-fami…

20251020周一日记

20251020周一日记为什么上周五没写日记?因为在集中办公耶! 周五: 1.早上开项目启动大会,一群老总来,有点像誓师大会。开始干活,第一天还没啥人吃零食。 2.下午上课,本来说是要汇报?结果老师微笑着走了忘了这事…

WPF loading data asynchronously and contextmenu save as json in mvvm

Install-Package Prism.Wpf; Install-Package Prism.DryIOC; Install-Package System.Text.Json;<prism:PrismApplication x:Class="WpfApp36.App"xmlns="http://schemas.microsoft.com/winfx/2006/…

Android 源码解析系列1- Android init 进程启动流程

Android 源码解析系列1- Android init 进程启动流程Android 源码解析系列1- Android init 进程启动流程 init进程是用户空间的第一个进程.如下 g1930fua_g210_ai:/ $ ps -ef | grep init #uid pid ppid C…