题目大意:给一个字符串,求所有相邻两回文子串的外侧下标之积的和

题目分析:另L[i]为所有以 i 为右端点的回文字串的左端点之和,同理,另R[i]表示所有以 i 为左端点的回文子串的右端点之和。显然,答案为sigma(L[i]*R[i+1]) 其中,1<=i<length(字符串)。求出L和R是关键。先用manacher算法处理出p数组,然后再求出L和R。求L和R的思想(非常巧妙)跟树状数组求区间和的思想差不多。不过,这道题如果用树状数组或线段树的话会超时。

参考代码:

# include<iostream>
# include<cstdio>
# include<cstring>
# include<algorithm>
using namespace std;
# define LL long long const int mod=1000000007;
const int N=1000000; char str[N+5];
char m[(N<<1)+5];
int p[(N<<1)+5]; LL addtag[2][N+5];
LL subtag[2][N+5];
LL addcnt[2][N+5];
LL subcnt[2][N+5];
LL val[2][N+5]; void manacher(char *ch)
{
int len=strlen(ch+1);
int cnt=0;
m[cnt++]='@';
m[cnt++]='#';
for(int i=1;i<=len;++i){
m[cnt++]=ch[i];
m[cnt++]='#';
}
m[cnt]='\0';
int id,mx=0;
for(int i=1;i<cnt;++i){
if(mx>i) p[i]=min(mx-i,p[2*id-i]);
else p[i]=1;
while(m[i-p[i]]==m[i+p[i]]) ++p[i];
if(i+p[i]>mx){
mx=i+p[i];
id=i;
}
}
} void update(int id,int l,int r,int a)
{
addtag[id][l]+=a;
addtag[id][l]%=mod;
++addcnt[id][l];
subtag[id][r+1]+=a-r+l;
subtag[id][r+1]%=mod;
++subcnt[id][r];
} void pushDown(int n)
{
for(int i=1;i<=n;++i){
if(addcnt[0][i]){
val[0][i]+=addtag[0][i];
val[0][i]%=mod;
addtag[0][i+1]+=addtag[0][i]-addcnt[0][i];
addtag[0][i+1]%=mod;
addcnt[0][i+1]+=addcnt[0][i];
}
if(subcnt[0][i]){
val[0][i]-=subtag[0][i];
val[0][i]%=mod;
subtag[0][i+1]+=subtag[0][i]-subcnt[0][i];
subtag[0][i+1]%=mod;
subcnt[0][i+1]+=subcnt[0][i];
}
if(addcnt[1][i]){
val[1][i]+=addtag[1][i];
val[1][i]%=mod;
addtag[1][i+1]+=addtag[1][i]-addcnt[1][i];
addtag[1][i+1]%=mod;
addcnt[1][i+1]+=addcnt[1][i];
}
if(subcnt[1][i]){
val[1][i]-=subtag[1][i];
val[1][i]%=mod;
subtag[1][i+1]+=subtag[1][i]-subcnt[1][i];
subtag[1][i+1]%=mod;
subcnt[1][i+1]+=subcnt[1][i];
}
}
} int main()
{
while(~scanf("%s",str+1))
{
manacher(str);
memset(val,0,sizeof(val));
memset(addtag,0,sizeof(addtag));
memset(subtag,0,sizeof(subtag));
memset(addcnt,0,sizeof(addcnt));
memset(subcnt,0,sizeof(subcnt));
for(int i=1;m[i];++i){
if(i&1){
if(p[i]==1) continue;
update(0,i/2+1,i/2+p[i]/2,i/2);
update(1,i/2-p[i]/2+1,i/2,i/2+p[i]/2);
}else{
int id=i/2;
int l=(p[i]-1)/2;
update(0,id,id+l,id);
update(1,id-l,id,id+l);
}
}
int n=strlen(str+1);
pushDown(n);
LL ans=0;
for(int i=1;i<n;++i){
ans+=val[0][i]*val[1][i+1];
ans%=mod;
}
while(ans<0) ans+=mod;
printf("%lld\n",ans);
}
return 0;
}

  

HDU-5785 Interesting(Manacher算法+区间处理)的更多相关文章

  1. HDU 5785 Interesting manacher + 延迟标记

    题意:给你一个串,若里面有两个相邻的没有交集的回文串的话,设为S[i...j] 和 S[j+1...k],对答案的贡献是i*k,就是左端点的值乘上右端点的值. 首先,如果s[x1....j].s[x2 ...

  2. HDU 5785 Interesting

    题目: 大概说给一个字符串,找到其所有子串[i...k]满足它是由两个回文串拼成的,求Σi*k. 分析: 用val[1][i]表示以i结尾的回文串的起始位置的和val[0][i]表示以i起始的回文串的 ...

  3. hdu 3068 最长回文 (Manacher算法求最长回文串)

    参考博客:Manacher算法--O(n)回文子串算法 - xuanflyer - 博客频道 - CSDN.NET 从队友那里听来的一个算法,O(N)求得每个中心延伸的回文长度.这个算法好像比较偏门, ...

  4. Manacher 算法(hdu 3068 && hdu 3294)

    今天打算补前晚 BC 的第二题,发现要用到能在 O(n) 时间求最大回文子串长度的 Manacher 算法,第一次听,于是便去百度了下,看了大半天,总算能看懂了其思想,至于他给出的代码模板我没能完全看 ...

  5. hdu 3068 最长回文 manacher算法(视频)

    感悟: 首先我要Orz一下qsc,我在网上很难找到关于acm的教学视频,但偶然发现了这个,感觉做的很好,链接:戳戳戳 感觉这种花费自己时间去教别人的人真的很伟大. manacher算法把所有的回文都变 ...

  6. HDU 5371(2015多校7)-Hotaru&#39;s problem(Manacher算法求回文串)

    题目地址:HDU 5371 题意:给你一个具有n个元素的整数序列,问你是否存在这样一个子序列.该子序列分为三部分,第一部分与第三部分同样,第一部分与第二部分对称.假设存在求最长的符合这样的条件的序列. ...

  7. HDU 3068:最长回文(Manacher算法)

    http://acm.hdu.edu.cn/showproblem.php?pid=3068 最长回文 Problem Description   给出一个只由小写英文字符a,b,c...y,z组成的 ...

  8. HDU 3068 最长回文 Manacher算法

    Manacher算法是个解决Palindrome问题的O(n)算法,能够说是个超级算法了,秒杀其它一切Palindrome解决方式,包含复杂的后缀数组. 网上非常多解释,最好的解析文章当然是Leetc ...

  9. hdu 3613"Best Reward"(Manacher算法)

    传送门 题意: 国王为了犒劳立下战功的大将军Li,决定奖给Li一串项链,这个项链一共包含26中珠子"a~z",每种珠子都有 相应的价值(-100~100),当某个项链可以构成回文时 ...

随机推荐

  1. <select>标签使用方法

    前台页面: <form id="form1" runat="server"> <select runat="server" ...

  2. SharePoint 2013 Nintex Workflow 工作流帮助(五)

    博客地址 http://blog.csdn.net/foxdave 工作流动作 4. Assign To-Do Task(User interaction分组) 直观理解,指派待办任务给一个或多个用户 ...

  3. hdu 2092

    Ps:wa了两次....一次是从加法那边暴力,然而算法错误..应该从乘法那边暴力破解...然而又没算负数..加上负数..直接暴力AC. 代码: #include "stdio.h" ...

  4. 外部表与partition

    在建立普通表的时候,如果数据是有分区的,在ADD DATA的时候需要指明分区,比方下面的例子: user表,包含 id bigint,name string,然后按照时间(date)来进行分区,路径存 ...

  5. linux添加动态库搜索路径

    在有时运行程序出现动态库找不着的问题,而明明装了的.这时候可能是没有将相应的路径添加到系统中去. 具体说:cd /etc/ld.so.conf.d/ 可以发现里面有一堆*.conf的文件 我们要做的就 ...

  6. Tomcat容器运行struts2+spring+mybatis架构的java web应用程序简单分析

    1.具体的环境为 MyEclipse 8.5以及自带的tomcat spring3.0.5 struts2.3.15.1 mybatis3.0.5 2.想弄明白的一些问题 tomcat集成spring ...

  7. iOS- 利用AFNetworking(AFN) - 实现图片上传

    官方建议AFN的使用方法 1. 定义一个全局的AFHttpClient:包含有 1> baseURL 2> 请求 3> 操作队列 NSOperationQueue 2. 由AFHTT ...

  8. Moto G如何进入开发者选项

    最近买了个Moto G做应用开发,突然发现开发者选项居然没有,搜索了一下发现是Google隐藏了此选项. http://allaboutmotog.com/moto-g-how-to-guide/ac ...

  9. FR #1题解

    A. 建图跑最小费用最大流.分类讨论每种情况如何连边,费用怎么定. #include<iostream> #include<cstdio> #include<cstrin ...

  10. div居中问题

    首们需要position:absolute搜索;绝对定位. 而层的定位点,使用外补丁margin负值的方法. 负值的大小为层自身宽度高度除以二. div {      position:absolut ...