题目描述

$ASDFZ$的机房中不仅有红太阳,还有蓝太阳和原谅色太阳。
有一天,太阳们来到机房,发现桌上有不知道哪个蒟蒻放上的问题:
令$F(A,B)$表示选择一个串$A$的非空前缀$S$和串$B$的非空后缀$T$使得将串$S$和串$T$拼起来之后是回文串的方案数。
现在给定两个串$A$和$B$,令$A_i$表示串$A$的第$i$长的后缀,$B_i$为串$B$的第$i$长的前缀。
有$Q$组询问,第$i$组询问给定$x_i$和$y_i$,对每组询问求$F(A_{x_i},B_{y_i})$的值。
太阳们非常强,自然不会把时间花在这种水题上。快来做做这个题呀。


输入格式

第一行一个字符串$str$,表示数据类型。
接下来的两行分别表示字符串$A$和$B$。
接下来一行一个正整数$Q$,表示询问的个数。
接下来$Q$行,每行两个正整数$x_i$和$y_i$。


输出格式

输出$Q$行,每行一个整数,表示这一组询问的答案。


样例

样例输入:

B
newionyzz
wyxioiwen
1
1 1

样例输出:

16


数据范围与提示

样例解释:

一共有以下$16$种方案:

$\{S=n,T=n\};\{S=n,T=en\};\{S=ne,T=n\};\{S=ne,T=en\};\{S=ne,T=wen\};\{S=new,T=en\};\{S=new,T=wen\};\{S=new,T=iwen\};\{S=new,T=ioiwen\};\{S=newi,T=wen\};\{S=newi,T=iwen\};\{S=newi,T=oiwen\};\{S=newio,T=iwen\};\{S=newio,T=oiwen\};\{S=newio,T=ioiwen\};\{S=newion,T=oiwen\};$

数据范围:

对于$100\%$的数据,字符串中只出现小写字母。

数据类型:$A:$随机数据,$B:$串$A$随机生成且$|B|\leqslant {10}^4$,$C:$无特殊性质。


题解

使用二分$+hash$判断以每个位置为中心延伸出去的回文串长度,这样会对一个区间的起点或终点的回文串个数产生$1$的贡献,差分一下最后前缀和一遍即可。
对于询问,注意到每次询问只要求一个区间内的$f$和$g$的和,前缀和即可。
每次通过二分$+hash$求$LCP$,得到最长的$l$。
时间复杂度:$\Theta((\max(|A|,|B|)+Q)\log(\max(|A|,|B|)))$。
最后$3$分显然是出题人想卡你自然溢出$hash$,所以就不要挣扎了。


代码时刻

#include<bits/stdc++.h>
using namespace std;
char A[800001],B[800001];
int q;
int lenA,lenB;
long long flag[800001],pre_A[800001],suc_A[800001],pre_B[800001],suc_B[800001],f[800001],g[800001],F[800001],G[800001];
void pre_work()
{
flag[0]=1;
for(int i=1;i<=800000;i++)
flag[i]=flag[i-1]*13131%1000000007;
for(int i=1;i<=lenA;i++)
{
pre_A[i]=(pre_A[i-1]*13131%1000000007+A[i]-'a'+1)%1000000007;
suc_A[i]=(suc_A[i-1]*13131%1000000007+A[lenA-i+1]-'a'+1)%1000000007;
}
for(int i=1;i<=lenB>>1;i++)B[i]^=B[lenB-i+1]^=B[i]^=B[lenB-i+1];
for(int i=1;i<=lenB;i++)
{
pre_B[i]=(pre_B[i-1]*13131%1000000007+B[i]-'a'+1)%1000000007;
suc_B[i]=(suc_B[i-1]*13131%1000000007+B[lenB-i+1]-'a'+1)%1000000007;
}
}
int preA(int L,int R){return(pre_A[R]-pre_A[L-1]*flag[R-L+1]%1000000007+1000000007)%1000000007;}
int sucA(int L,int R){return(suc_A[R]-suc_A[L-1]*flag[R-L+1]%1000000007+1000000007)%1000000007;}
int preB(int L,int R){return(pre_B[R]-pre_B[L-1]*flag[R-L+1]%1000000007+1000000007)%1000000007;}
int sucB(int L,int R){return(suc_B[R]-suc_B[L-1]*flag[R-L+1]%1000000007+1000000007)%1000000007;}
bool checkA(int L,int R)
{
if(L<1||R>lenA)return 0;
return preA(L,R)==sucA(lenA-R+1,lenA-L+1);
}
bool checkB(int L,int R)
{
if(L<1||R>lenB)return 0;
return preB(L,R)==sucB(lenB-R+1,lenB-L+1);
}
int find_A(int L,int R)
{
int lft=1,rht=lenA;
while(lft<rht-1)
{
int mid=(lft+rht)>>1;
if(checkA(L-mid+1,R+mid-1))lft=mid;
else rht=mid;
}
if(checkA(L-rht+1,R+rht-1))return L-rht+1;
return L-lft+1;
}
int find_B(int L,int R)
{
int lft=1,rht=lenB;
while(lft<rht-1)
{
int mid=(lft+rht)>>1;
if(checkB(L-mid+1,R+mid-1))lft=mid;
else rht=mid;
}
if(checkB(L-rht+1,R+rht-1))return L-rht+1;
return L-lft+1;
}
void pre_do_A()
{
for(int i=1;i<=lenA;i++)
{
f[find_A(i,i)]++;
f[i+1]--;
if(A[i]==A[i+1])
{
f[find_A(i,i+1)]++;
f[i+1]--;
}
}
for(int i=1;i<=lenA+1;i++)
{
f[i]+=f[i-1];
F[i]=F[i-1]+f[i];
}
}
void pre_do_B()
{
for(int i=1;i<=lenB;i++)
{
g[find_B(i,i)]++;
g[i+1]--;
if(B[i]==B[i+1])
{
g[find_B(i,i+1)]++;
g[i+1]--;
}
}
for(int i=1;i<=lenB+1;i++)
{
g[i]+=g[i-1];
G[i]=G[i-1]+g[i];
}
}
int LCP(int L,int R)
{
int lft=0,rht=min(lenA-L+1,lenB-R+1);
while(lft<rht-1)
{
int mid=(lft+rht)>>1;
if(preA(L,L+mid-1)==preB(R,R+mid-1))lft=mid;
else rht=mid;
}
if(preA(L,L+rht-1)==preB(R,R+rht-1))return rht;
return lft;
}
int main()
{
scanf("%s%s%s%d",A,A+1,B+1,&q);
lenA=strlen(A+1),lenB=strlen(B+1);
pre_work();
pre_do_A();
pre_do_B();
while(q--)
{
int x,y;
scanf("%d%d",&x,&y);
int len=LCP(x,y);
printf("%lld\n",F[x+len]-F[x]+G[y+len]-G[y]+len);
}
return 0;
}

rp++

[CSP-S模拟测试]:回文串(hash+二分)的更多相关文章

  1. [CSP-S模拟测试]:回文(hash+二维前缀和)

    题目描述 闲着无聊的$YGH$秒掉上面两道题之后,开始思考有趣的回文串问题了. 他面前就有一个漂浮着的字符串.显然$YGH$是会$manacher$的,于是他随手求出了这个字符串的回文子串个数.但是他 ...

  2. BZOJ4755 JSOI2016扭动的回文串(二分答案+哈希)

    显然答案应该是由单串以某位置为中心的极长回文串继续在另一个串里拓展得到的.枚举中间位置二分答案,哈希判断即可.注意考虑清楚怎么处理偶回文,比如像manacher一样加分隔符. #include< ...

  3. 【BZOJ4755】扭动的回文串(Manacher,哈希)

    [BZOJ4755]扭动的回文串(Manacher,哈希) 题面 BZOJ 题解 不要真的以为看见了回文串就是\(PAM,Manacher\)一类就可以过. 这题显然不行啊. 我们主要考虑如何解决跨串 ...

  4. bzoj 3676 回文串 manachar+hash

    考虑每个回文串,它一定是它中心字母的最长回文串两侧去掉同样数量的字符后的一个子串. 所以我们可以用manachar求出每一位的回文半径,放到哈希表里并标记出它的下一个子串. 最后拓扑排序递推就行了.. ...

  5. SPOJ - PLSQUARE Palin Squar(hash+回文串)

    题意:给你一个n*n (n<=200)的字符串矩阵,问你每行每列都是回文串的最大的m*m的矩阵是多少 题解:首先答案不满足单调性,即m成立而m-1与m+1都却不一定成立,所以必须枚举答案确定现在 ...

  6. 【GDOI2016模拟3.15】基因合成(回文串+性质+DP)

    [GDOI2016模拟3.15]基因合成 题意: 给一个目标串,要求从空串进行最少的操作次数变成目标串,操作有两种: 在串的头或尾加入一个字符. 把串复制一遍后反向接到串的末尾. 因为有回文操作,所以 ...

  7. bzoj 2124 等差子序列 树状数组维护hash+回文串

    等差子序列 Time Limit: 3 Sec  Memory Limit: 259 MBSubmit: 1919  Solved: 713[Submit][Status][Discuss] Desc ...

  8. Gym - 100570E:Palindrome Query (hash+BIT+二分维护回文串长度)

    题意:给定字符串char[],以及Q个操作,操作有三种: 1:pos,chr:把pos位置的字符改为chr 2:pos:问以pos为中心的回文串长度为多长. 3:pos:问以pos,pos+1为中心的 ...

  9. LOJ 2452 对称 Antisymmetry——用hash求回文串数

    概念 用hash求最长回文串/回文串数 首先,易知,回文串具有单调性. 如果字符串 $s[l...r]$ 为回文串串,那么 $s[x...y]$($l < x, y < r$ 且 $|l- ...

随机推荐

  1. shtml与html

    前言 在浏览网页的时,忽然发现了一个网址不是以[.html]结尾,而是[.shtml].顿时勾起了我的好奇心,这是什么鬼?于是打开google,开始维基. SHTML 什么是 SHTML 使用SSI( ...

  2. linux常用命令介绍

    参考博客: https://www.cnblogs.com/caozy/p/9261224.html 学前理论 linux主要特征 :一切且文件(目录.硬盘等都是文件):硬件都在/dev 目录,如硬盘 ...

  3. Git008--远程仓库

    Git--远程仓库 本文来自于:https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/ ...

  4. sed删除注释行和空行

    典型需求: 删除nginx.conf文件中注释行和空行 sed -i '/^#/d;/^$/d' nginx.conf 删除一个或多个空格加 # 号的行 sed -i '/[:blank:]*#/d' ...

  5. mybatis配置mapper.xml 的基本操作

    XML 映射文件 本文参考mybatis中文官网进行学习总结:http://www.mybatis.org/mybatis-3/zh/sqlmap-xml.html MyBatis 的真正强大在于它的 ...

  6. 线上服务器CPU100%排查

    某服务器上部署了若干tomcat实例,即若干垂直切分的Java站点服务,以及若干Java微服务,突然收到运维的CPU异常告警. 问:如何定位是哪个服务进程导致CPU过载,哪个线程导致CPU过载,哪段代 ...

  7. display:table的几个用法

    DIV+CSS的布局已经让表格布局几乎很少用到,除非表格语义性很强的情况. display:table解决了一部分需要使用表格特性但又不需要表格语义的情况, 尤其是DIV+CSS很不方便解决的问题,比 ...

  8. beeline链接hive报错

    看问题:beeline连接hiveserver2报错.连接串:hive  --service beeline -u jdbc:hive2://localhost:10000/hive 错误:Error ...

  9. activity 生命周期 http://stackoverflow.com/questions/8515936/android-activity-life-cycle-what-are-all-these-methods-for

    331down voteaccepted See it in Activity Lifecycle (at Android Developers). onCreate(): Called when t ...

  10. Ubuntu18.04+CUDA9.0+cuDNN7.1.3+TensorFlow1.8 安装总结

    Ubuntu18.04发行已经有一段时间了,正好最近Tensorflow也发布了1.8版本,于是决定两个一起装上,以下是安装总结,大致可 以分为5个步骤 确认当前软件和硬件环境.版本 更新显卡驱动,软 ...