BZOJ4755 [JSOI2016]扭动的回文串 【后缀数组】【manacher】
题目分析:
我写了史上最丑的后缀数组,怎么办?
首先manacher一遍两个串,这样只用考虑第三问。用$作为间隔符拼接两个串,把第一个串翻转。枚举回文中心,取最长的回文串,对于剩下的部分利用LCP匹配即可。
代码:
#include<bits/stdc++.h>
using namespace std; #define Sec first.second
#define Fir first.first const int maxn = ; int n,as,f[maxn],sa[maxn],height[maxn],h[maxn],rk[maxn*];
string s1,s2,vk;
int RMQ[maxn][]; void read(){cin >> n; cin >> s1 >> s2;}
int pf[maxn][]; void manacher(string &str){
vk.clear();
memset(f,,sizeof(f));
for(int i=;i<n;i++) vk.push_back(str[i]),vk.push_back('$');
f[] = ; int last = ,ct = ;
for(int i=;i<*n;i++){
f[i] = ;
if(i <= ct+last- && i+f[*ct-i]- <= ct+last-) f[i]=f[*ct-i];
while(i-f[i]>=&&i+f[i]<*n&&vk[i-f[i]]==vk[i+f[i]]){f[i]++;}
if(ct+last- < i+f[i]-) ct = i,last = f[i];
}
}
int X[maxn];
pair<pair<int,int>,int> pr[maxn];
vector <pair<int,int> > vec[maxn];
void get_sa(){
int z = s1.length();
for(int i=;i<z;i++) X[s1[i]]++;
for(int i=;i<=;i++)X[i] += X[i-];
for(int i=;i<z;i++) rk[i] = X[s1[i]];
for(int k=;(<<k)<=z;k++){
for(int i=;i<z;i++)
vec[rk[i+(<<k-)]].push_back(make_pair(rk[i],i));
//pr[i+1]=make_pair(make_pair(rk[i],rk[i+(1<<k-1)]),i);
//sort(pr+1,pr+z+1);
for(int i=,tms=;i<=z;i++)
for(int j=vec[i].size()-;j>=;j--){
pr[++tms]=make_pair(make_pair(vec[i][j].first,i),vec[i][j].second);
vec[i].pop_back();
}
for(int i=z;i>=;i--)
vec[pr[i].Fir].push_back(make_pair(pr[i].Sec,pr[i].second));
for(int i=,tms=;i<=z;i++)
for(int j=vec[i].size()-;j>=;j--){
pr[++tms] = make_pair(make_pair(i,vec[i][j].first),vec[i][j].second);
vec[i].pop_back();
}
int num = ;
for(int i=;i<=z;i++){
if(pr[i].first == pr[i-].first) rk[pr[i].second]=num;
else num++,rk[pr[i].second] = num;
}
}
for(int i=;i<z;i++) sa[rk[i]] = i;
}
void get_height(){
int z = s1.length();
for(int i=;i<z;i++){
if(i) h[i] = max(,h[i-]-); else h[i] = ;
if(rk[i]==) continue;
comp = sa[rk[i]-];
while(s1[comp+h[i]] == s1[i+h[i]])h[i]++;
}
for(int i=;i<z;i++) height[rk[i]] = h[i];
for(int i=;i<=z;i++) RMQ[i][] = height[i];
for(int k=;(<<k)<=z;k++){
for(int i=;i<=z;i++){
if(i+(<<k-)>z) RMQ[i][k] = RMQ[i][k-];
else RMQ[i][k] = min(RMQ[i][k-],RMQ[i+(<<k-)][k-]);
}
}
}
int getLCP(int L,int R){
if(L == R) return n-sa[L]; if(L > R) swap(L,R); L++;
int k = ; while((<<k+)<=R-L+)k++;
return min(RMQ[L][k],RMQ[R-(<<k)+][k]);
} void work(){
manacher(s1);
for(int i=;i<*n;i++) pf[i][] = f[i];
manacher(s2);
for(int i=;i<*n;i++) pf[i][] = f[i];
for(int i=;i<n/;i++) swap(s1[i],s1[s1.length()-i-]);
s1.push_back('$');
for(int i=;i<n;i++) s1.push_back(s2[i]);
get_sa(); get_height();
for(int i=;i<*n;i+=) {
if(pf[i][]%==)pf[i][]--;
int z = (i-pf[i][]+)/,w = (i+pf[i][]-)/;
int L = rk[n-z],R = rk[n+w+];
if(L > R) swap(L,R); int len = getLCP(L,R); as=max(as,w-z++len*);
if(pf[i][]%==)pf[i][]--;
z = (i-pf[i][]+)/,w = (i+pf[i][]-)/;
L = rk[n-z-],R = rk[n+w+];
if(L > R) swap(L,R); len = getLCP(L,R); as = max(as,w-z++len*);
}
for(int i=;i<*n;i+=) {
if(pf[i][]&) pf[i][]--;
int z = i-pf[i][]+,w = i+pf[i][]-;
if(pf[i][] == ){
int L = rk[n-(i-)/-],R = rk[n++(i-)/];
if(L > R) swap(L,R);int len=getLCP(L,R);as=max(as,len*);
} else{
z/=,w/=; int L = rk[n-z],R = rk[n++w];
if(L > R) swap(L,R);int len=getLCP(L,R);as=max(as,w-z++len*);
}
if(pf[i][]&) pf[i][]--;
z = i-pf[i][]+,w = i+pf[i][]-;
if(pf[i][] == ){
int L = rk[n-(i-)/-],R = rk[n++(i-)/];
if(L>R) swap(L,R); int len = getLCP(L,R); as = max(as,len*);
}else{
z/=,w/=; int L = rk[n-z-],R = rk[n+w+];
if(L > R) swap(L,R);int len=getLCP(L,R);as=max(as,w-z++len*); }
}
printf("%d",as);
} int main(){
//freopen("2.in","r",stdin);
read();
work();
return ;
}
BZOJ4755 [JSOI2016]扭动的回文串 【后缀数组】【manacher】的更多相关文章
- [bzoj4755][Jsoi2016]扭动的回文串
来自FallDream的博客,未经允许,请勿转载,谢谢. JYY有两个长度均为N的字符串A和B. 一个“扭动字符串S(i,j,k)由A中的第i个字符到第j个字符组成的子串与B中的第j个字符到第k个字符 ...
- BZOJ4755: [JSOI2016]扭动的回文串——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=4755 JYY有两个长度均为N的字符串A和B. 一个“扭动字符串S(i,j,k)由A中的第i个字符到 ...
- BZOJ4755 JSOI2016扭动的回文串(二分答案+哈希)
显然答案应该是由单串以某位置为中心的极长回文串继续在另一个串里拓展得到的.枚举中间位置二分答案,哈希判断即可.注意考虑清楚怎么处理偶回文,比如像manacher一样加分隔符. #include< ...
- [bzoj3676]回文串[后缀数组+Manacher]
后缀数组+Manacher #include <iostream> #include <cstdio> #include <cstdlib> #include &l ...
- [BZOJ4755][JSOI2016]扭动的回文串(manacher+Hash)
前两种情况显然直接manacher,对于第三种,枚举回文中心,二分回文半径,哈希判断即可. #include<cstdio> #include<algorithm> #defi ...
- 【BZOJ4755】 [Jsoi2016]扭动的回文串
BZOJ4755 [Jsoi2016]扭动的回文串 Solution 考虑对于他给出的 A中的一个回文串: B中的一个回文串: 或者某一个回文的扭动字符串S(i,j,k) 这样子几个限制,我们1,2就 ...
- 【BZOJ4755】扭动的回文串(Manacher,哈希)
[BZOJ4755]扭动的回文串(Manacher,哈希) 题面 BZOJ 题解 不要真的以为看见了回文串就是\(PAM,Manacher\)一类就可以过. 这题显然不行啊. 我们主要考虑如何解决跨串 ...
- [BZOJ]4755: [Jsoi2016]扭动的回文串
Time Limit: 10 Sec Memory Limit: 512 MB Description JYY有两个长度均为N的字符串A和B. 一个"扭动字符串S(i,j,k)由A中的第i ...
- 【题解】Luogu P4324 [JSOI2016]扭动的回文串
原题传送门 这题实际挺水的 先对两个字符串分别跑马拉车 就能求出1.2类扭动回文串最大的长度 考虑第三类的扭动回文串\(S(i,j,k)\),一定可以表示为\(A(i,l)+A(l+1,j)+B(j, ...
随机推荐
- RPM包制作过程(一)
本机环境:centos7,64位 1. 首先安装工具,rpmbuild可能在rpmdevtools里已经包含 #yum install rpm-devel.x86_64 #yum install rp ...
- 二、截取字符串长度(css方式)
只针对谷歌 width: 100%; //height: 58px; overflow:hidden; text-overflow:ellipsis; display: -webkit-box; -w ...
- scrapy框架原理学习
Scrapy框架原理: 参考出处:https://cuiqingcai.com/3472.html 整个Scrapy的架构图: Scrapy Engine: 这是引擎,负责Spiders.ItemPi ...
- PS调出怀旧雨中特写的非主流照片
原图 最终效果 一.打开原图素材,按Ctrl + ALt + ~ 调出高光选区,按Ctrl + Shift + I 反选,然后创建曲线调整图层,适当调暗一点. 二.合并所有图层,点通道面板,选择蓝色通 ...
- openstack-虚拟化模型
一. 虚拟化模型 1.虚拟化模型 图1 虚拟化模型 图2 KVM架构 2.KVM模块 处理器虚化 内存虚化 3.QEMU设备模型 其它虚化(网卡.声卡.显卡等)
- pdf中内嵌字体问题
在提交论文pdf到IEEE时总要检查字体是否为内嵌的,查看pdf中所有字体及是否内嵌可查看:http://sinme.blog.sohu.com/120043575.html. 具体做法是: 在pdf ...
- beego 各种形式的路由实例
基本路由 基本路由就是和http.Handle和http.HandleFunc一样都是绑定固定的路径,比如绑定了4个路由映射: 定义的4个控制器中,匹配哪一个路由,就输出对应的控制名. beego.R ...
- 学习PHPExcel
关于PHPExcel使用方法,可以参考慕课网的教程,链接在此 PHPExcel的github地址:https://github.com/PHPOffice/PHPExcel 下载之后,将文件夹中的Cl ...
- 【Python3练习题 019】 有一分数序列:2/1,3/2,5/3,8/5,13/8,21/13...求出这个数列的前20项之和。
后一个分数的分子=前一个分数的分子+分母,后一个分数的分母=前一个分数的分子,循环个20次就有结果.注意,假设分子为a,分母为b,虽然 a = a + b, 但此时a已经变成 a+b 了,所以再给b重 ...
- IdentityServer4【QuickStart】之利用OpenID Connect添加用户认证
利用OpenID Connect添加用户认证 利用OpenID Connect添加用户认证 在这个示例中我们想要通过OpenID Connect协议将交互用户添加到我们的IdentityServer上 ...