[JSOI2008 Prefix火星人]

[关键字]:splay hash 二分

[题目大意]:给出一个字符串,求出给定的两个后缀的的最长公共前缀。在求的过程中会有改变或在某个位置添加字符的操作。

//============================================================================================

[分析]:一听最长公共前缀马上想到后缀数组,但因为是动态维护所以后缀数组也无能为力。可以把字符串想象成一个数组,于是变成了动态插入和改变一个序列,还要能快速找到两个子区间——splay。求最长公共前缀可以用二分答案加验证的方法,二分长度先提取出这个区间然后判断这个区间的根节点的hash值(实际就是这棵子树的hash)是否和另一个相同。hash值得判断可以用进制法:hash=ord(s[1])*270+ord(s[2])*271+……+ord(s[n])*27n-1,在旋转时更新hash值为:hash[lc]+s[v]*27^(size[lc]+1)+hash[rc]*27^(size[lc]+2)。插入操作和一般splay插入无异修改只要修改掉这个点的值和hash值就行了。

[代码]:

View Code
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;const int MAXL=100015;
const int MOD=9875321;struct node
{node *c[2],*f;int dat,size,hash;
}*root,SC[MAXL],*null;
char s[MAXL];
int m,SS;
int d[MAXL];void Debug(node *v)
{if (v==null) return;Debug(v->c[0]);printf("%d ",v->dat);Debug(v->c[1]);
}node *New(int d,int h,node *fa)
{node *e=SC+ ++SS;e->size=1,e->f=fa;e->c[1]=e->c[0]=null;e->dat=d,e->hash=h;return e;
}void Update(node *v)
{if (v==null) return;v->size=v->c[0]->size+v->c[1]->size+1;v->hash=(long long)(v->c[0]->hash+(long long)v->dat*d[(v->c[0]->size+1)]+(long long)v->c[1]->hash*d[(v->c[0]->size+2)])%MOD;
}void Prepare()
{SS=-1;null=NULL;null=New(0,0,NULL);null->size=0;root=New(0,0,null);root->c[1]=New(0,0,root);d[1]=1;for (int i=2;i<=100010;++i)d[i]=(d[i-1]*27)%MOD;Update(root);
}void Rotate(node *x,int o)
{node *y=x->f;y->c[o]=x->c[!o];y->c[o]->f=y;x->f=y->f;if (y->f->c[0]==y)y->f->c[0]=x;elsey->f->c[1]=x;x->c[!o]=y;y->f=x;if (y==root) root=x;Update(y);
}void Splay(node *x,node *fa)
{while (x->f!=fa)if (x->f->f==fa)if (x->f->c[0]==x)Rotate(x,0);elseRotate(x,1);elseif (x->f->f->c[0]==x->f)if (x->f->c[0]==x)Rotate(x->f,0),Rotate(x,0);elseRotate(x,1),Rotate(x,0);else    if (x->f->c[1]==x)Rotate(x->f,1),Rotate(x,1);elseRotate(x,0),Rotate(x,1);Update(x);
}void Select(int k,node *fa)
{node *t=root;while (1){if (k==t->c[0]->size+1) break;if (k<t->c[0]->size+1) t=t->c[0];if (k>t->c[0]->size+1) k-=t->c[0]->size+1,t=t->c[1];}Splay(t,fa);
}int Hash(int x,int y)
{Select(x,null),Select(y+2,root);return root->c[1]->c[0]->hash;
}void Ask(int x,int y)
{int ans=0,n=root->size-2;for (int i=1<<18;i;i>>=1)if (x+i-1<=n && y+i-1<=n && Hash(x,x+i-1)==Hash(y,y+i-1))ans+=i,x+=i,y+=i;printf("%d\n",ans);
}void Ins(int x,char ch)
{Select(x+1,null),Select(x+2,root);root->c[1]->c[0]=New(ch-'a',ch-'a',root->c[1]);Splay(root->c[1]->c[0],null);//Debug(root),printf("\n");
}void Rep(int x,char ch)
{Select(x,null),Select(x+2,root);node *v=root->c[1]->c[0];v->dat=ch-'a';v->hash=(long long)(v->c[0]->hash+(long long)v->dat*d[(v->c[0]->size+1)]+(long long)v->c[1]->hash*d[(v->c[0]->size+2)])%MOD;//Debug(root),printf("\n");
}void Init()
{node *z,*t;Prepare();scanf("%s",s);int n=strlen(s);z=t=New(s[0]-'a',s[0]-'a',null);for (int i=1;i<n;++i)z=z->c[1]=New(s[i]-'a',s[i]-'a',z);root->c[1]->c[0]=t,t->f=root->c[1];Splay(z,null);//Debug(root),printf("\n");
}void Solve()
{char ch; int x,y;scanf("%d",&m),scanf("%c",&ch);for (int i=1;i<=m;++i){scanf("%c",&ch);if (ch=='Q') scanf("%d %d",&x,&y),Ask(x,y); elseif (ch=='I') scanf("%d %c",&x,&ch),Ins(x,ch); elsescanf("%d %c",&x,&ch),Rep(x,ch);scanf("%c",&ch);}
}int main()
{freopen("in","r",stdin);freopen("out","w",stdout);Init();Solve();return 0;
}

转载于:https://www.cnblogs.com/procedure2012/archive/2012/04/13/2445062.html

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

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

相关文章

简单实用方法!!

简单验证码生成&#xff01;&#xff01; protected void Page_Load(object sender, EventArgs e) { string CharList "0123456789"; int[] size { 10, 12, 14 }; string[] fm { "宋体", "楷体_G…

浅谈微信小程序生命周期

之前在做微信小程序的时候&#xff0c;一直对生命周期里面的onLoad&#xff0c;onShow&#xff0c;onUnload不是很理解。比如说什么时候会触发onUnload。 经过一段时间的测试发现&#xff0c;普通页面的onUnload在三种情况下会触发。 某一个页面跳转到tabBar页面&#xff0c;根…

POJ 1013 Counterfeit Dollar 称硬币

12个硬币&#xff0c;有一个假的 或轻或重&#xff0c;找出假硬币 开始用的模拟&#xff0c;考虑很多情况 后来&#xff0c;lmy说轻的-1&#xff0c;重的1&#xff0c;学数学的看什么都是数字&#xff0c;orz 模拟写的两个差不多的代码&#xff1a; (一&#xff09; #include&l…

DELPHI学习---结构类型

Structured types (结构类型) 结构类型的一个实例可包含多个值。结构类型包括集合、数组、记录&#xff0c;也包括类、类引用&#xff08;class-reference&#xff09; 和接口类型。除了集合只能包含有序值以外&#xff0c;结构类型可以包含其它的结构类型&#xff0c;且结构的…

ios学习笔记block回调的应用(一个简单的例子)

一、什么是Blocks Block是一个C级别的语法以及运行时的一个特性&#xff0c;和标准C中的函数&#xff08;函数指针&#xff09;类似&#xff0c;但是其运行需要编译器和运行时支持&#xff0c;从ios4.0开始就很好的支持Block。 二、在ios开发中&#xff0c;什么情况下使用…

vue定义global.js,挂载在vue原型上面使用

首先在src目录下创建global目录&#xff0c;在global目录下创建index.js。 export default {install(Vue) {var that this// 1. 添加全局方法或属性// ue.global this// 2. 添加全局资源// 3. 注入组件Vue.mixin({created() {this.global that}})// 大于一的整数验证&#x…

Configuration、SessionFactory、Session

org.hibernate.cfg Class Configuration An instance of Configuration allows(允许) the application to specify properties and mapping documents to be used when creating a SessionFactory. Usually an application will create a single Configuration, build a singl…

函数声明指令(stdcall, cdecl,pascal,register)

指令 参数存放位置 参数传递顺序 参数内存管理 适用地点registerCPU寄存器从左到右被调用者默认&#xff0c;published 属性存取方法必须使用pascal栈从左到右被调用者向后兼容cdecl栈从右到左调用者调用 C 共享库stdcall栈从右到左被调用者API 调用safecall栈从右到左被调用…

uni-app相关

uni-app 中以下组件的高度是固定的&#xff0c;不可修改&#xff1a; 导航栏高度固定为 44pxtabBar 高度固定为 56px 状态栏比较特殊&#xff0c;是一个变量 .status_bar{height: var(--status-bar-height);width: 100%; } uni-app 使用 vue/cli 创建项目的时候&#xff0c;如果…

《Windows游戏编程大师技巧》三、Windows高级编程

Windows编程很绝的地方在于&#xff1a;你不用了解太多细节&#xff0c;就可以完成很多工作。使用资源资源就是你的程序代码结合在一起的多块数据&#xff0c;可以被程序本身在运行时加载。资源应当也放在程序的.EXE文件中的原因是&#xff1a;1.同时包含代码和数据的.EXE文件更…

结构型模式--装饰模式

下面先用java&#xff0c;然后用Objective&#xff0d;C行对装饰模式的讲解&#xff1a; 对于java的装饰模式讲解和使用比较详细和难度有点偏高&#xff0c;而对于Objective&#xff0d;C的装饰模式讲解和使用方面比较简单&#xff0c;而且和java的装饰模式略有差异&#xff0c…

ArcGIS.Server.9.2.DotNet自带例子分析(三、一)

目的&#xff1a; 1.arcgis server9.2 ADF的AddGraphics。 准备工作&#xff1a; 1.用ArcGis Server Manager或者ArcCatalog发布一个叫world的Map Service,并且把这个Service启动起来。 2.找到DeveloperKit\SamplesNET\Server\Web_Applications目录下的Common_AddGraphicsCShar…

linux 使用timedatectl 修改时区和时间

使用timedatectl可以进行如下常见操作 1.查看当前时间/日期/时区&#xff1a;timedatectl或者timedatectl status 2.查看所有可用时区&#xff1a;timedatectl list-timezones 3.设置时区&#xff1a;timedatectl set-timezone “Asia/Shanghai” 或者 timedatectl set-time…

aspose将datatable导出excel 比自己拼好的多 Bug少-。.net

using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.IO; using System.Data; using Aspose.Cells; /// <summary> ///OutFileDao 的摘要说明 /// </summary> publicclass OutFileDao { public OutFileDa…

【MVC】AJAX+PartialView实现商城首页的楼层加载

使用AJAX实现楼层加载的例子已经非常多&#xff0c;但是html代码大都是手动拼接的&#xff0c;编写不便&#xff0c;而且难以维护。 下面就使用AJAXPartialView来实现 1.html代码 <!--楼层1开始--> <div class"floor" id"floor1"></div>…

VS2008常用快捷键

如果有一天&#xff0c;你的鼠标被猫叼走了的时候&#xff0c;你会发现这些快捷键很有意思&#xff0c;你的鼠标在的时候这些可爱的快捷键会让你更方便。 命令行&#xff1a; Devenv 启动VS Studion Isqlw 启动SQL2000查询分析器 Sqlwb 启动SQL2005企业管理器 Inet…

给控件动态添加方法

新建一个窗体,添加如下方法 public void init() { FormBuildStringControl formStringControl; FormBuildButtonControl formButtonControl; FormBuildGroupControl formGroupControl; ; // Adding a group formGroupControl this.form().addControl(FormControlType::Group, …

整理:Android apk 框架 布局 集锦

2019独角兽企业重金招聘Python工程师标准>>> 看到好的技术教程就想分享一下&#xff0c;不喜勿喷&#xff01;谢谢配合&#xff0c;仅供菜鸟学习研究(^o^)/~ 友情推荐《爱加密》Android apk加密保护视频教程剪辑&#xff1a;http://www.ijiami.cn/Video?v3 Andro…

IE8不兼容你的网页 怎么办? - 简单开启兼容模式

自从用了IE8 整个世界都变了形.   呵呵,问题没那么严重,如果你的网站还来不及修改以适合IE8访问的时候,咱们可以通过非常简单的方法,加几行代码就可以让访问的IE8自动调用IE7的渲染模式[/b],这样可以保证最大的兼容性,方法如下:   只需要在页面中加入如下HTTP meta-tag:  …

springboot打war包汇总

概述 第一次用maven工具打war包&#xff0c;出现各种各样的问题&#xff0c;做个问题记录方便下次查看 maven 一开始用的maven是springboot默认的&#xff0c;在.m2下&#xff0c;要打包时才发现没有mvn指令。索性自己就重新装个maven&#xff0c;去官网下载&#xff0c;我安装…