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, ...
随机推荐
- Signalr实现消息推送
一.前言 大多数系统里面好像都有获取消息的功能,但这些消息来源都不是实时的,比如你开两个浏览器,用两个不同的账号登录,用一个账号给另外一个账号发送消息,然而并不会实时收到消息,必须要自己手动F5刷新一 ...
- 朱晔的互联网架构实践心得S1E7:三十种架构设计模式(上)
朱晔的互联网架构实践心得S1E7:三十种架构设计模式(上) [下载本文PDF进行阅读] 设计模式是前人通过大量的实践总结出来的一些经验总结和最佳实践.在经过多年的软件开发实践之后,回过头来去看23种设 ...
- ubuntu中更改apache默认目录的方法
如上,在这两个文件中,我都改为/home/www 及/home/www/html
- Shell脚本2
5 Shell传递参数 我们可以在执行 Shell 脚本时,向脚本传递参数, 脚本内获取参数的格式为:$n.n 代表一个数字,1 为执行脚本的第一个参数,2 为执行脚本的第二个参数,以此类推…… ...
- 初次使用beego框架
安装beego框架以及bee工具 go get -u github.com/astaxie/beego go get github.com/beego/bee 创建一个新项目 bee new weba ...
- jvisualvm远程监控 visualgc插件 不受此jvm支持问题
https://yq.aliyun.com/ziliao/478212 1.修改远程服务器上java设置 vi $JAVA_HOME/jre/lib/security/java.policy 在 ...
- 渗透测试平台bwapp简单介绍及安装
先来介绍一下bwapp bwapp是一款非常好用的漏洞演示平台,包含有100多个漏洞 SQL, HTML, iFrame, SSI, OS Command, XML, XPath, LDAP, PHP ...
- MySQL 性能调优之存储引擎
原文:http://bbs.landingbj.com/t-0-246222-1.html http://bbs.landingbj.com/t-0-245851-1.html MySQ ...
- java 获取下一个字母(传大写返回大写,传小写返回小写)
public static String getNextUpEn(String en){ char lastE = 'a'; char st = en.toCharArray()[0]; if(Cha ...
- php 对象赋值后改变成员变量影响赋值对象
话不多说看代码 打印结果 对obj1的操作 直接影响了obj2 , 对obj2的操作 直接影响了obj1