SP3109 STRLCP - Longest Common Prefix 题解

news2024/11/25 2:37:27

SP3109 STRLCP - Longest Common Prefix 题解

某省某年省选原题出处,看来 CCF 出原题这事由来已久。

简化题意

  1. 让你维护一个字符串序列。
  2. 支持单点修改。
  3. 支持单点插入。
  4. 支持询问两个子串的最长公共前缀。

解法

本篇题解前置芝士:无旋 Treap(FHQ Treap),哈希,二分。如果有不会的请自行查找资料学习。

如果没有单点插入操作,我们可以考虑使用线段树维护区间哈希值(我不会后缀自动机)。求最长公共前缀时可以二分最长公共前缀的长度,这里记作 m i d mid mid,判断两个字符串前 m i d mid mid 个字符是否相同(即哈希值相等),如果相同则证明答案不小于 m i d mid mid,将二分范围向右侧缩小,如果不相同则证明答案小于 m i d mid mid,将二分范围向左缩小。

为什么这题不能用普通线段树呢?因为单点插入操作会改变序列长度,就会改变线段树中父亲与儿子的关系。

那有没有能同时支持动态维护序列和区间信息的数据结构呢?有,平衡树可以动态维护序列。相信大家都会平衡树的基本操作了,这里只有合并区间信息这里和模板题不一样。所以我只讲如何合并区间信息。

先看线段树是如何合并区间哈希值的。

线段树

注意到平衡树的性质,根节点表示的点在左右子树表示的区间的中间。所以类似于线段树的区间合并,平衡树的区间合并是三个区间的合并。

平衡树

查询 [ l , r ] [l,r] [l,r] 区间的哈希值时可以将平衡树分裂成 [ 1 , l − 1 ] , [ l , r ] , [ r + 1 , L ] [1,l-1],[l,r],[r+1,L] [1,l1],[l,r],[r+1,L] 三棵平衡树,查询后再将三棵平衡树合并即可。 L L L 表示当前序列的长度。

综上,平衡树的时间复杂度是 O ( ( L + c ) log ⁡ L + q log ⁡ 2 L ) \mathcal{O}((L + c) \log L + q \log^2 L) O((L+c)logL+qlog2L),分别是建树、修改、查询的时间复杂度,其中 q q q 表示操作中查询次数, c c c 表示操作中修改次数。

代码

#include<bits/stdc++.h>
namespace fast_IO
{
	/**
	 * 快读快写
	*/
};
using namespace fast_IO;
const int base=131;
int t,n,m,l,r,mid,ans;
char op,ch;
unsigned int pw[100010];
std::string st;
struct fhq_node
{
	int w,siz;
	unsigned int val,has;
	fhq_node *lc,*rc;
	inline fhq_node(unsigned int val)
	{
		this->val=has=val,w=rand(),siz=1,lc=rc=nullptr;
	}
	inline void pushup()
	{
		siz=(lc==nullptr?0:lc->siz)+(rc==nullptr?0:rc->siz)+1;
		if(lc==nullptr && rc==nullptr) has=val;
		else if(lc==nullptr) has=val*pw[rc->siz]+rc->has;
		else if(rc==nullptr) has=lc->has*pw[1]+val;
		else has=lc->has*pw[rc->siz+1]+val*pw[rc->siz]+rc->has;
	}
};
class fhq_treap
{
private:
	fhq_node *root;
	inline fhq_node *merge(fhq_node *l,fhq_node *r)
	{
		if(l==nullptr) return r;
		if(r==nullptr) return l;
		if(l->w<r->w)
		{
			l->rc=merge(l->rc,r),l->pushup();
			return l;
		}else
		{
			r->lc=merge(l,r->lc),r->pushup();
			return r;
		}
	}
	inline std::pair<fhq_node *,fhq_node *> split(fhq_node *rt,const int &k)
	{
		std::pair<fhq_node *,fhq_node *> ret;
		if(rt==nullptr) return std::make_pair(nullptr,nullptr);
		int left=rt->lc==nullptr?0:rt->lc->siz;
		if(k<=left) ret=split(rt->lc,k),rt->lc=ret.second,rt->pushup(),ret.second=rt;
		else ret=split(rt->rc,k-left-1),rt->rc=ret.first,rt->pushup(),ret.first=rt;
		return ret;
	}
	inline void clear(fhq_node *rt)
	{
		if(rt==nullptr) return;
		if(rt->lc!=nullptr) clear(rt->lc);
		if(rt->rc!=nullptr) clear(rt->rc);
		delete rt;
	}
public:
	inline int getsiz()
	{
		return root->siz;
	}
	inline void clear()
	{
		clear(root),root=nullptr;
	}
	inline void fix(const int &pos,const unsigned int val)
	{
		std::pair<fhq_node *,fhq_node *> a,b;
		a=split(root,pos),b=split(a.first,pos-1);
		b.second->val=b.second->has=val,root=merge(merge(b.first,b.second),a.second);
	}
	inline void insert(const int &pos,const unsigned int val)
	{
		fhq_node *rt=new fhq_node(val);
		std::pair<fhq_node *,fhq_node *> a;
		a=split(root,pos),root=merge(merge(a.first,rt),a.second);
	}
	inline unsigned int ask(const int &L,const int &R)
	{
		std::pair<fhq_node *,fhq_node *> a,b;
		a=split(root,R),b=split(a.first,L-1);
		unsigned int ret=b.second->has;
		root=merge(merge(b.first,b.second),a.second);
		return ret;
	}
};
fhq_treap tree;
int main()
{
	srand(time(0)),pw[0]=1;
	for(int i=1;i<=100001;i++) pw[i]=pw[i-1]*base;
	in>>t;
	while(t--)
	{
		in>>st>>m,st="#"+st,n=st.size()-1,tree.clear();
		for(int i=1;i<=n;i++) tree.insert(i,st[i]-'a'+1);
		for(int i=1,x,y;i<=m;i++)
		{
			in>>op>>x;
			if(op=='Q')
			{
				in>>y;
				if(x>y) std::swap(x,y);
				l=1,r=tree.getsiz()-y+1,ans=0;
				while(l<=r)
				{
					mid=(l+r)/2;
					if(tree.ask(x,x+mid-1)==tree.ask(y,y+mid-1)) ans=mid,l=mid+1;
					else r=mid-1;
				}
				out<<ans<<'\n';
			}else if(op=='R') in>>ch,tree.fix(x,ch-'a'+1);
			else in>>ch,tree.insert(x,ch-'a'+1);
		}
	}
	fwrite(Ouf,1,p3-Ouf,stdout),fflush(stdout);
	return 0;
}

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

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

相关文章

孔明棋,(n + 2) x (m + 2)的棋盘,中间n x m的区域都是棋子,求最后最少剩余几个棋子

题目 #include <iostream> using namespace std; int f(int n, int m) {int t, res;if (n > m){t n;n m;m t;}if (n 1)res (m 1) / 2;else if (n 2){if (m % 3 0)res 2;elseres 1;}else if (n 3){res 2;}return res; } int change(int x) {x % 3;if (x 0…

OpenHarmony亮相MTSC 2023 | 质量效率共进,赋能应用生态发展

11月25日&#xff0c;MTSC 2023第十二届中国互联网测试开发大会在深圳登喜路国际大酒店圆满举行。大会以“软件质量保障体系和测试研发技术交流”为主要目的&#xff0c;旨在为行业搭建一个深入探讨和交流的桥梁和平台。OpenAtom OpenHarmony&#xff08;简称“OpenHarmony”&a…

AI一键生成文案-免费AI一键生成文案的软件有哪些

AI一键生成文案的原理涉及自然语言处理&#xff08;NLP&#xff09;和机器学习技术。这种技术的核心是基于大量文本数据的模式识别和生成&#xff0c;通常使用深度学习模型&#xff0c;如循环神经网络&#xff08;RNN&#xff09;、长短期记忆网络&#xff08;LSTM&#xff09;…

六、Lua运算符

文章目录 一、Lua 运算符&#xff08;一&#xff09;算术运算符&#xff08;二&#xff09;关系运算符&#xff08;三&#xff09;逻辑运算符&#xff08;四&#xff09;其他运算符 二、运算符优先级 一、Lua 运算符 运算符是一个特殊的符号&#xff0c;用于告诉解释器执行特定…

【双指针】四数之和

四数之和 建议做过了解三数之和的思想再做这道题&#xff0c;思路是一样的~ 题目描述 18. 四数之和 - 力扣&#xff08;LeetCode&#xff09; 给你一个由 n 个整数组成的数组 nums &#xff0c;和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [num…

第1章 理解知识图谱(一)

&#x1f497;&#x1f497;&#x1f497;欢迎来到我的博客&#xff0c;你将找到有关如何使用技术解决问题的文章&#xff0c;也会找到某个技术的学习路线。无论你是何种职业&#xff0c;我都希望我的博客对你有所帮助。最后不要忘记订阅我的博客以获取最新文章&#xff0c;也欢…

大模型的开源闭源

文章目录 开源&闭源开源和闭源的优劣势比较开源和闭源对大模型技术发展的影响开源与闭源的商业模式比较国内的大模型开源和闭源的现状和趋势 开源和闭源&#xff0c;两种截然不同的开发模式&#xff0c;对于大模型的发展有着重要影响。 开源让技术共享&#xff0c;吸引了众…

【objectarx.net】table问题2:添加table后,保存时出错

添加table后&#xff0c;保存时出现以上对话框。 原因&#xff1a; tb.TableStyle db.Tablestyle; 对于这句代码&#xff0c;tb所在的数据库和db不是同一个。

数据库SQL小技巧大揭秘:IGNORE选项让你的数据处理更从容

点击上方蓝字关注我 在 MySQL 中&#xff0c;IGNORE 是一种在插入或更新数据时处理冲突的选项。具体来说&#xff0c;在 INSERT | UPDATE 语句中&#xff0c;IGNORE 的作用是在插入或更新数据时忽略特定的错误&#xff0c;而不导致整个操作失败。另外&#xff0c;IGNORE 选项还…

开发定制化抖音票务小程序的技术解析

通过定制化抖音票务小程序&#xff0c;可以为用户提供更加个性化的活动体验&#xff0c;同时也为企业和品牌提供了更多的营销机会。 一、小程序开发框架的选择 在开发定制化抖音票务小程序之前&#xff0c;选择合适的小程序开发框架至关重要。目前&#xff0c;主流的小程序框…

如何用Python批量删除视频的头尾(88)

小朋友们好&#xff0c;大朋友们好&#xff01; 我是猫妹&#xff0c;一名爱上Python编程的小学生。 关注我&#xff0c;一起趣味学编程&#xff01; 今天我们继续用Python玩转视频。 还是用Python的第三方库moviepy。 如果你对此文章感兴趣的话&#xff0c;可以看看之前的…

mysql 命令行导入sql 数据,windows导入,强制导入

线上用了polarDB&#xff0c; 本地导入的时候&#xff0c;通过navicat 的备份导入和执行sql文件的方式导入都失败了 用命令行的方式可以导入sql 当我用windows 的cmd 导入的时候&#xff0c;会报一些命令行的错误。 那其实我检查了这个命令是没有问题的。 mysql -uroot -p hu…

文本生成超逼真歌曲,谷歌推出音乐模型Lyria

转换示例 谷歌旗下的DeepMind与视频平台YT合作&#xff0c;发布了目前最先进的音乐模型——Lyria。 为了突破传统音乐模型的生硬机器感&#xff0c;谷歌汇集了多个部门并与Charlie Puth、T-Pain、Troye Sivan等9位知名音乐人共同研发了Lyria。 Lyria可生成爵士、重金属、摇滚…

配置zabbix-proxy主动式

IP地址对应关系如下&#xff1a; zabbix-server122.9.8.21zabbix-proxy122.9.4.102zabbix-agent2116.63.9.109 一、 安装zabbix-server https://blog.csdn.net/qq_50247813/article/details/132131774 二、 安装zabbix-proxy a. 安装zabbix源 rpm -Uvh https://repo.zabbix…

Swift构造器继承链

类类型的构造器代理 Swift构造器需遵循以下三大规则&#xff1a; 指定构造器必须调用它直接父类的指定构造器方法便利构造器必须调用同一个类中定义的其他初始化方法便利构造器在最后必须调用一个指定构造器 两段式构造过程 Swift 中类的构造过程包含两个阶段。第一个阶段&a…

流程控制翻转学习

&#x1f4d1;前言 本文主要是【Python】——Python流程控制翻转学习的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是听风与他&#x1f947; ☁️博客首页&#xff1a;CSDN主页听风与他 &#x1f304;每…

STM32_10(I2C)

I2C通信 I2C&#xff08;Inter IC Bus&#xff09;是由Philips公司开发的一种通用数据总线两根通信线&#xff1a;SCL&#xff08;Serial Clock&#xff09;、SDA&#xff08;Serial Data&#xff09;同步&#xff0c;半双工带数据应答支持总线挂载多设备&#xff08;一主多从…

Elasticsearch 线上实战问题及解决方案探讨

1、reindex相关问题 1.1 问题描述 我有 1tb 的一个大索引若干&#xff0c;要迁移到另外一个新集群去&#xff0c;有没有好办法&#xff1f;reindex好像会中断...... reindex 是不是就算设置了频率也会莫名的中断&#xff0c;而且没地方查到错误&#xff1f;1000多万的数据&…

盖茨表示GPT-5不会比GPT-4有太大改进;Intro to Large Language Models

&#x1f989; AI新闻 &#x1f680; 盖茨表示GPT-5不会比GPT-4有太大改进 摘要&#xff1a;比尔盖茨在与德国《商报》的采访中透露&#xff0c;虽然OpenAI内部有人相信GPT-5会优于GPT-4&#xff0c;但他认为目前的生成式人工智能已经达到极限。盖茨对GPT-5未来的发展并不乐观…

视频集中存储/磁盘阵列EasyCVR平台黑名单异常解决步骤是什么?

视频云存储/安防监控EasyCVR视频汇聚平台基于云边端智能协同&#xff0c;支持海量视频的轻量化接入与汇聚、转码与处理、全网智能分发、视频集中存储等。音视频流媒体视频平台EasyCVR拓展性强&#xff0c;视频能力丰富&#xff0c;具体可实现视频监控直播、视频轮播、视频录像、…