JSOI 2016 扭动的字符串

题面描述

给出两个长度为\(n\)的字符串\(A,B\)

\(S(i,j,k)\)表示把\(A\)中的\([i,j]\)和\(B\)中的\([j,k]\)拼接起来的字符串

问所有回文的\(S(i,j,k)\)或者\(A,B\)中的回文子串的最长长度

思路

枚举回文串的中心。

可以发现,如果能在当前字符串内扩展就尽量扩展,不能扩展了再尝试和另一个字符串匹配。

对于前者,使用\(manacher\)算法

对于后者,二分一个长度,用\(hash\)判断能否匹配。

以上

代码

#include<bits/stdc++.h>
#define pii pair<int,int>
#define mkp(x,y) make_pair(x,y)
using namespace std;
const int sz=2e5+7;
const int p1=998244353;
const int p2=1e8+7;
const int q1=5271314;
const int q2=2374899;
int n,m;
int ans;
int p[2][sz];
char s[2][sz];
char ss[2][sz<<1];
int w[2][sz];
int pre[2][2][sz],suf[2][2][sz];//字符串,哈希,位置
void init(int tp){
int mid=0,r=0;
for(int i=1;i<=m;i++){
if(i<r) p[tp][i]=min(r-i,p[tp][2*mid-i]);
else p[tp][i]=1;
while(ss[tp][i+p[tp][i]]==ss[tp][i-p[tp][i]]) p[tp][i]++;
if(i+p[tp][i]>r) mid=i,r=i+p[tp][i];
}
}
void hash(int tp){
int hs0,hs1;
hs0=hs1=0;
for(int i=1;i<=n;i++){
hs0=(1ll*hs0*q1%p1+s[tp][i])%p1;
hs1=(1ll*hs1*q2%p2+s[tp][i])%p2;
pre[tp][0][i]=hs0;
pre[tp][1][i]=hs1;
}
hs0=hs1=0;
for(int i=n;i>=1;i--){
hs0=(1ll*hs0*q1%p1+s[tp][i])%p1;
hs1=(1ll*hs1*q2%p2+s[tp][i])%p2;
suf[tp][0][i]=hs0;
suf[tp][1][i]=hs1;
}
}
pii gs(int tp,int st,int l){
int sum1=pre[tp][0][st]-1ll*w[0][l]*pre[tp][0][st-l]%p1;
int sum2=pre[tp][1][st]-1ll*w[1][l]*pre[tp][1][st-l]%p2;
if(sum1<0) sum1+=p1;
if(sum2<0) sum2+=p2;
return mkp(sum1,sum2);
}
pii gn(int tp,int st,int l){
int sum1=suf[tp][0][st]-1ll*w[0][l]*suf[tp][0][st+l]%p1;
int sum2=suf[tp][1][st]-1ll*w[1][l]*suf[tp][1][st+l]%p2;
if(sum1<0) sum1+=p1;
if(sum2<0) sum2+=p2;
return mkp(sum1,sum2);
}
int main(){
scanf("%d",&n);
scanf("%s",s[0]+1);
scanf("%s",s[1]+1);
ss[0][0]=ss[1][0]='#';
ss[0][1]=ss[1][1]='|';
for(int i=1;i<=n;i++){
ss[0][2*i]=s[0][i];
ss[1][2*i]=s[1][i];
ss[0][2*i+1]=ss[1][2*i+1]='|';
}
m=2*n+1;
w[0][0]=w[1][0]=1;
for(int i=1;i<=n;i++){
w[0][i]=1ll*w[0][i-1]*q1%p1;
w[1][i]=1ll*w[1][i-1]*q2%p2;
}
init(0),init(1);
hash(0),hash(1);
int L,R,sl,sr,len,l,r,mid;
for(int i=2;i<m;i++){
L=i-p[0][i],R=i+p[0][i];
sl=L/2,sr=R/2-1;
len=p[0][i]-1;
l=0,r=min(sl,n-sr+1);
while(l<r){
mid=(l+r+1)>>1;
if(gs(0,sl,mid)==gn(1,sr,mid)) l=mid;
else r=mid-1;
}
ans=max(ans,len+2*l);
}
for(int i=2;i<m;i++){
L=i-p[1][i],R=i+p[1][i];
sl=L/2+1,sr=R/2;
len=p[1][i]-1;
l=0,r=min(sl,n-sr+1);
while(l<r){
mid=(l+r+1)>>1;
if(gs(0,sl,mid)==gn(1,sr,mid)) l=mid;
else r=mid-1;
}
ans=max(ans,len+2*l);
}
printf("%d\n",ans);
}

JSOI 2016 扭动的字符串的更多相关文章

  1. [JSOI 2016] 最佳团体(树形背包+01分数规划)

    4753: [Jsoi2016]最佳团体 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 2003  Solved: 790[Submit][Statu ...

  2. 解题:JSOI 2016 最佳团体

    题面 0/1分数规划+树形背包检查 要求$\frac{\sum P_i}{\sum S_i}的最大值,$按照0/1分数规划的做法,二分一个mid之后把式子化成$\sum P_i=\sum S_i*mi ...

  3. [JSOI 2016] 灯塔

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=4850 [算法] 首先对不等式进行移项 : hj <= hi + p - sqr ...

  4. [JSOI 2016] 最佳团体

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=4753 [算法] 很明显的分数规划 可以用树形动态规划(树形背包)检验答案 时间复杂度 ...

  5. JSOI 2016 病毒感染 辅助Dp问题

    原题链接:https://www.luogu.com.cn/problem/P5774 分析 直接看这道题,第一个困惑点,那个绝对值的比较是什么东西,根据数学知识,我们可以知道这个意思是k到i的距离小 ...

  6. 《JAVASCRIPT高级程序设计》JSON语法/解析/序列化

    JSON是一种数据格式,不是一种编程语言. 一.语法 JSON语法可以表示以下三种类型的值:简单值.对象.数组. 1.简单值 最简单的JSON数据值就是简单值: 5 "hello world ...

  7. Chrome 调试技巧

    Chrome 调试技巧 1.alert 这个不用多说了,不言自明. 可参考:https://www.cnblogs.com/Michelle20180227/p/9110028.html 2.cons ...

  8. Python连接Access数据库

    前言 今天想要用Python访问Access数据库,折腾了半天,特记录一下 背景 最近想将一些文件记录下来,存入数据库,为此拿LabVIEW写了一个版本,记录环境配置为: LabVIWE:2015 A ...

  9. JNI_Z_08_创建Java对象

    1.步骤 : (1).获取 jclass (2).获取 构造函数的 method id (方法的名称始终为"<init>") (3).创建Java对象的两种方式: (3 ...

随机推荐

  1. BigDecimal踩过的大坑

    通常Java中涉及金钱相关的计算为了保持精度,会采用BigDecimal来实现,但是BigDecimal中创建BigDecimal类对象的时候,如果使用直接new的话,必须是String类型的参数,否 ...

  2. 使用ProGuard混淆JAR包

    1.在Input/OutPut选项下面,add input 导入需要混淆的jar包2.点击add output,设置混淆后输出jar包的名字和路径.如下图:3.在下面的编辑区右边点击add增加要混淆的 ...

  3. php数据结构课程---7、队列实战

    php数据结构课程---7.队列实战 一.总结 一句话总结: 注意条件:注意循环的条件(比如while循环打印队列元素时),注意if的条件 把问题想清楚:比如链表操作初次插入元素和后面再插,效果是不一 ...

  4. VS2010-MFC(菜单:菜单及CMenu类的使用)

    转自:http://www.jizhuomi.com/software/212.html 上一节讲的是VS2010的菜单资源,本节主要讲菜单及CMenu类的使用. CMenu类的主要成员函数 MFC为 ...

  5. SPSS分类分析:决策树

    SPSS分类分析:决策树 一.决策树(分析-分类-决策树) "决策树"过程创建基于树的分类模型.它将个案分为若干组,或根据自变量(预测变量)的值预测因变量(目标变量)的值.此过程为 ...

  6. Spring MVC(十六)--Spring MVC国际化实例

    上一篇文章总结了一下Spring MVC中实现国际化所需的配置,本文继上一文举一个完整的例子,我选择用XML的方式.我的场景是这样的: 访问一个页面时,这个页面有个表格,对表头中的列名实现国际化. 第 ...

  7. python语句结构(range函数)

    python语句结构(range函数) range()函数 如果你需要遍历数字序列,可以使用内置range()函数,它会生成序列 也可以通过range()函数指定序列的区间 也可以使用range()函 ...

  8. docker上安装ActiveMQ

    1.查看是否已经存在镜像 docker images 2.搜索镜像 docker search activemq 3.拉取镜像 docker pull webcenter/activemq 4.构建容 ...

  9. js 仿微信投诉—引入vue.js,拆分组件为单个js

    效果 页面目录 index.html <!DOCTYPE html > <html> <head> <meta charset="UTF-8&quo ...

  10. 查看linux的shhd端口号 netstat | grep sshd

    [root@iZ2zef51hufoaycipfxek8Z ~]# [root@iZ2zef51hufoaycipfxek8Z ~]# netstat | grep sshd [root@iZ2zef ...