manachermanachermanacher+二分+双哈希

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

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

  1. 当TTT是AAA串或BBB串中的一个回文串时,我们可以直接用manachermanachermanacher求得答案。

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

假设我们现在枚举iii是在AAA串,我们有这么一个结论:

TTT的长度至少是以iii为中点在AAA串中的最长回文串的长度,即hwA[i]−1hwA[i]-1hwA[i]−1。

也就是说,TTT中肯定包含A[i−hwA[i]+1...i+hwA[i]−1]A[i-hwA[i]+1...i+hwA[i]-1]A[i−hwA[i]+1...i+hwA[i]−1]。

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

也就是说,这个扭动字符串S(i,j,k)S(i,j,k)S(i,j,k)的jjj就是i+hwA[i]−1i+hwA[i]-1i+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;
}

【loj2073】「JSOI2016」扭动的回文串(manacher+二分+双哈希)相关推荐

  1. loj#2073. 「JSOI2016」扭动的回文串

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

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

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

  3. 【JSOI2016】扭动的回文串

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

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

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

  5. 洛谷 P4324 [JSOI2016]扭动的回文串 manacher+字符串hash

    题目描述 JYY有两个长度均为 NNN 的字符串 AAA 和 BBB. 一个扭动字符串 S(i,j,k)S(i,j,k)S(i,j,k) 由 AAA 中的第 iii 个字符到第 jjj 个字符组成的子 ...

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

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

  7. [JSOI2016]扭动的回文串

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

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

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

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

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

最新文章

  1. vue3.0环境搭建
  2. Node Sass does not yet support your current environment: Windows 64-bit然如何解决,cnpm此问题解决方法
  3. 前端学习(1410):多人管理30数据分页
  4. linux档案权限655,Linux学习笔记之档案权限与目录配置
  5. 安装nginx、drizzle和lua
  6. 后端实体类接收数组_三级联动返回数组的方式
  7. 病毒——隐藏鸟 系统文件夹不见了
  8. Libhybris之Glibc和Bionic共存时的TLS问题(四)
  9. mybatis开发中遇到的小问题
  10. torch中permute()函数用法补充内容(矩阵维度变化详细过程)
  11. 写写做数模竞赛的经验
  12. 解决“应用程序无法启动,因为应用程序的并行配置不正确“问题
  13. Selenium 批量执行url(附完整代码)
  14. OrCAD42道问题汇总
  15. hp 计算机如何显示在桌面上,HPDL1414 精致桌面小伴侣 显示时间日历和电脑状态(CPU温度负载...
  16. OpenGL 渲染直线
  17. Micron(美光)内存颗粒的命名规则,7lk17d9PTK,MT29F2G08ABAEA(矿机自带)
  18. css3切角文本框_CSS3样式linear-gradient的使用(切角效果)
  19. php 上传 413,PHP CURL上传文件出现413 Request Entity Too Large
  20. 创建 JCEKS 密钥库

热门文章

  1. java中super用来定义父类,定义子类必须使用的关键字是 在java中子类若要继承父类,需要使用的关键字是什么...
  2. 百度云盘服务器升级,从云储存工具升级为云操作系统,百度网盘将成为百度5G物联入口...
  3. pycharm中django框架连接mysql数据库
  4. hive--union all后无数据/少数据
  5. 新版ECharts实现“暂无数据”的完美解决方案
  6. Gitbook 插件安装 - 导航目录折叠 chapter-fold
  7. C++结构体定义及申请空间
  8. linux 文件中查找内容
  9. 【Leetcode】883. 三维形体投影面积
  10. unity小技巧收集总结--自用(一)