\(manacher\)+二分+双哈希

看见标题就不想做的童鞋可以看下面,让你更绝望。

这题思路比较简单明了,我们就按照题目说的那样,设串\(T\)为答案,分两种情况讨论:

  1. 当\(T\)是\(A\)串或\(B\)串中的一个回文串时,我们可以直接用\(manacher\)求得答案。

  2. 当\(T\)是某一个回文的扭动字符串\(S(i,j,k)\)时,我们可以枚举这个串\(T\)的中点\(i\)是在\(A\)串还是在\(B\)串,然后解法如下:

假设我们现在枚举\(i\)是在\(A\)串,我们有这么一个结论:

\(T\)的长度至少是以\(i\)为中点在\(A\)串中的最长回文串的长度,即\(hwA[i]-1\)。

也就是说,\(T\)中肯定包含\(A[i-hwA[i]+1...i+hwA[i]-1]\)。

然后因为\(A[i-hwA[i]]!=A[i+hwA[i]]\),所以我们可以直接从\(A[i-hwA[i]]\)和\(B[i+hwA[i]-1]\)开始枚举就行了。

也就是说,这个扭动字符串\(S(i,j,k)\)的\(j\)就是\(i+hwA[i]-1\)了。

至于之后的枚举,直接枚举会比较麻烦,我们可以二分长度,用前缀和板双哈希来判断。

最后的代码如下:

#include<bits/stdc++.h>#define N 200010
#define p1 100007
#define p2 233333
#define limit 27using namespace std;int len,ans,ra[N],rb[N],standard[2][N],suma[2][N],sumb[2][N];
char a[N],b[N];void init()//现在字符串中插入'#'
{for(int i=len;i>=0;i--){a[i<<1]=a[i],b[i<<1]=b[i];a[i<<1|1]=b[i<<1|1]='#';}len=len<<1|1;a[0]=b[0]='@',a[1]=b[1]='#',a[len+1]=b[len+1]='%',standard[0][0]=standard[1][0]=1;
}void manacher(char *s,int *radius)//manacher
{int maxright=0,mid;for(int i=1;i<=len;i++){if(i<maxright)radius[i]=min(radius[(mid<<1)-i],maxright-i+1);else radius[i]=1;while(s[i-radius[i]]==s[i+radius[i]])radius[i]++;if(i+radius[i]-1>maxright){maxright=i+radius[i]-1;mid=i;}}
}void gethash()//双哈希预处理
{for(int i=1;i<=len;i++)//计算类似于进制基本单位的东东{ans=max(ans,max(ra[i],rb[i]));//顺便统计答案standard[0][i]=(long long)standard[0][i-1]*limit%p1;standard[1][i]=(long long)standard[1][i-1]*limit%p2;}for(int i=2;i<len;i+=2)//计算前缀和{suma[0][i>>1]=((long long)suma[0][(i>>1)-1]*limit+a[i])%p1;suma[1][i>>1]=((long long)suma[1][(i>>1)-1]*limit+a[i])%p2;}for(int i=len-1;i>=1;i-=2){sumb[0][i>>1]=((long long)sumb[0][(i>>1)+1]*limit+b[i])%p1;sumb[1][i>>1]=((long long)sumb[1][(i>>1)+1]*limit+b[i])%p2;}
}bool check(int l1,int r1,int l2,int r2,int l)//双哈希检验
{int x=(suma[0][r1]-(long long)suma[0][l1-1]*standard[0][l]%p1)%p1;int y=(sumb[0][l2]-(long long)sumb[0][r2+1]*standard[0][l]%p1)%p1;x=(x+p1)%p1,y=(y+p1)%p1;if (x!=y)return false;//第一层哈希x=(suma[1][r1]-(long long)suma[1][l1-1]*standard[1][l]%p2)%p2;y=(sumb[1][l2]-(long long)sumb[1][r2+1]*standard[1][l]%p2)%p2;x=(x+p2)%p2;y=(y+p2)%p2;return x==y;//第二层哈希
}int solve(int x,int y)//二分
{int l=0,r=min(x,(len>>1)-y+1),ans=0;while(l<=r){int mid=(l+r)>>1;if(check(x-mid+1,x,y,y+mid-1,mid))l=mid+1,ans=mid;else r=mid-1;}return ans;
}void query()//枚举T的中点
{for(int i=2;i<len;i++)//T的中点在A串时{int l=i-ra[i],r=i+ra[i];l=(l+1)>>1,r>>=1;ans=max(ans,ra[i]+solve(l-1,r)*2);}for(int i=2;i<len;i++)//T的中点在B串时{int l=i-rb[i],r=i+rb[i];l=(l+1)>>1,r>>=1;ans=max(ans,rb[i]+solve(l,r+1)*2);}
}int main()
{scanf("%d%s%s",&len,a+1,b+1);init();manacher(a,ra);manacher(b,rb);for(int i=1;i<=len;i++)ra[i]--,rb[i]--;//计算回文长度gethash();query();printf("%d\n",ans);return 0;
}

转载于:https://www.cnblogs.com/ez-lcw/p/11168779.html

loj#2073. 「JSOI2016」扭动的回文串相关推荐

  1. 【loj2073】「JSOI2016」扭动的回文串(manacher+二分+双哈希)

    manachermanachermanacher+二分+双哈希 看见标题就不想做的童鞋可以看下面,让你更绝望. 这题思路比较简单明了,我们就按照题目说的那样,设串TTT为答案,分两种情况讨论: 当TT ...

  2. 【JSOI2016】扭动的回文串

    内存限制:256 MiB 时间限制:1000 ms 题目描述 JYY 有两个长度均为 N 的字符串 A 和 B. 一个「扭动字符串」S(i,j,k)S(i,j,k)S(i,j,k) 由 A 中的第 i ...

  3. 【BZOJ4755】【JSOI2016】扭动的回文串

    [题目链接] 点击打开链接 [思路要点] 一定存在一个最长的扭动回文串是从回文中心所在串的某一个极长回文子串开始,一侧向回文中心所在串匹配,另一侧扭向另一个串匹配.因为任意一个扭动的回文串都对应了一个 ...

  4. bzoj4755: [Jsoi2016]扭动的回文串 manacher+二分+Hash

    bzoj4755: [Jsoi2016]扭动的回文串 Description JYY有两个长度均为N的字符串A和B. 一个"扭动字符串S(i,j,k)由A中的第i个字符到第j个字符组成的子串 ...

  5. 【BZOJ4755】 [Jsoi2016]扭动的回文串

    BZOJ4755 [Jsoi2016]扭动的回文串 Solution 考虑对于他给出的 A中的一个回文串: B中的一个回文串: 或者某一个回文的扭动字符串S(i,j,k) 这样子几个限制,我们1,2就 ...

  6. [JSOI2016]扭动的回文串

    题目 非常板子了 看到求什么最长的回文,我们就想到枚举回文中心的方法 首先对于这个回文串只包含在一个串内的情况,我们随便一搞就可以了,大概\(Manacher\)一下就没有了 对于那种扭动的回文串,我 ...

  7. BZOJ4755 [Jsoi2016]扭动的回文串

    标签:Manacher,hash,二分 题目 题目传送门 Description JYY有两个长度均为N的字符串A和B. 一个"扭动字符串S(i,j,k)由A中的第i个字符到第j个字符组成的 ...

  8. bzoj 4755: [Jsoi2016]扭动的回文串 manachar+hash+二分

    题意 JYY有两个长度均为N的字符串A和B. 一个"扭动字符串S(i,j,k)由A中的第i个字符到第j个字符组成的子串与B中的第j个字符到第k个字符组成的子串拼接而成. 比如,若A='XYZ ...

  9. BZOJ4755: [JSOI2016]扭动的回文串——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=4755 JYY有两个长度均为N的字符串A和B. 一个"扭动字符串S(i,j,k)由A中的第 ...

最新文章

  1. 【每日一算法】最长公共前缀
  2. $GLOBALS['HTTP_RAW_POST_DATA'] 和$_POST的区别
  3. 2013-10-31 《三天里什么都没干……总之把目前为止的代码发了吧……》
  4. 一文教你 Dubbo 服务性能压测(with JMeter)
  5. cad2010背景怎么调成黑色_买皮蛋时,黄色和黑色的有什么区别?哪种更好?看完涨知识了...
  6. 『Linux基础 - 4 』linux常用命令(1)
  7. 一步步在Docker里运行Web应用
  8. 关于std::thread以及std::condition_variable的一些细节备忘
  9. nasm纠正性训练指南pdf_PDF转word,一键转换?没有这么简单
  10. Python实现学生出勤记录
  11. 新基建下 AI 算力市场崛起,华为凭什么从中分一杯羹?
  12. wangEditor关闭粘贴样式的过滤,解决小程序中xml溢出报错问题
  13. Mac小知识:只需四步,教大家如何修改苹果电脑的DNS
  14. 四十五.加密与解密 AIDE入侵检测系统 扫描与抓包
  15. 惠普电脑按F12锁屏如何解?
  16. 《不抱怨的世界》-- 威尔·鲍温(Will Bowen)
  17. 3D游戏编程与设计作业02
  18. 百度地图Js之浏览端
  19. underscorejs-pluck学习
  20. 计算机无法识别出cd驱动器,迅捷(FAST)免驱无线网卡插到电脑上无法识别CD驱动器怎么解决?【图解】...

热门文章

  1. ssm上传文件获取路径_ssm框架实现图片上传显示并保存地址到数据库(示例代码)...
  2. 虚拟机环境下ansible方式部署tidb3.0时系统检测不通过
  3. linux 后台运行_Linux系统后台运行应用三板斧
  4. java word另存为_Java 网页html转为word并保存为doc文件
  5. bootstrap下拉框分页_学习使用Bootstrap输入框、导航、分页等常用组件
  6. python语法类似php吗_深入学习PHP还是Python
  7. 使用Spring Boot发送邮件
  8. rabbitMQ碰到了对象跨项目的时候,反序列化出了问题
  9. java-jdk7新特性
  10. 多领域合作 浪潮与美亚柏科赋能信息安全