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, ...
随机推荐
- Google 宣布在 4 月 1 日关闭站内搜索
今春,Google 计划终止又一项产品,它就是“站内搜索”(Site Search)功能.这项产品主要出售给 web 出版商,让它们可以在自家网站内运用业内领先的搜索技术.虽然该公司并未公开宣布此事, ...
- p2394 精度题
题意:输出n/23即可 解法一: 利用高精度的long double直接输出,但由于n的长度不确定,我们要加个限制%12Lf #include <cstdio> int main(){ l ...
- git的用法步骤讲解
1.创建全局的本地用户名 git config --global user.name "teamemory" git config --global user.email &quo ...
- MyBatis模糊查询不报错但查不出数据的一种解决方案
今天在用MyBatis写一个模糊查询的时候,程序没有报错,但查不出来数据,随即做了一个测试,部分代码如下: @Test public void findByNameTest() throws IOEx ...
- Ajax中文乱码的解决
网上有很多解决Ajax中文乱码的例子,昨晚弄了很久,最终确定一种“确实”有效地方法.首先我有必要说明一下我遇到的情况:有一个注册页面,注册用户填完信息并提交后,页面获得信息并通过java servle ...
- [2017BUAA软工助教]第0次作业小结
BUAA软工第0次作业小结 零.题目 作业链接: This is a hyperlink 一.评分规则 本次作业满分10分: 按时提交有分 一周内补交得0分 超过一周不交或抄袭倒扣全部分数 评分规则如 ...
- 多线程系列之三:Immutable 模式
一,什么是Immutable模式?immutable就是不变的,不发生改变的.Immutable模式中存在着确保实例状态不发生变化改变的类.这些实例不需要互斥处理.String就是一个Immutabl ...
- Jenkins redeploy artifacts
jenkins redeploy artifacts 按钮 - 开源中国https://www.oschina.net/question/3045293_2247829 Jenkins 构建失败后通过 ...
- TortoiseGit push免输密码
(ฅ>ω<*ฅ) 噫又好了~ TortoiseGit push免输密码的方法 – 晨旭的博客~https://www.chenxublog.com/2016/03/04/tortoiseg ...
- ShowDoc上手
ShowDoc是什么 每当接手一个他人开发好的模块或者项目,看着那些没有写注释的代码,我们都无比抓狂.文档呢?!文档呢?!Show me the doc !! 程序员都很希望别人能写技术文档,而自己却 ...