HDU 5785 Interesting
题目:
大概说给一个字符串,找到其所有子串[i...k]满足它是由两个回文串拼成的,求Σi*k。
分析:
用val[1][i]表示以i结尾的回文串的起始位置的和val[0][i]表示以i起始的回文串的结尾位置的和,然后就可以求出答案了. Σ(val[1][i]*val[0][i+1])就是答案.
1.假设原串为a[]={aaa},使用manacher算法将原串变为#a#a#a#,对应的p数组为{1,2,3,4,3,2,1}.p[i]/2-1的值为新串中以i为中心的回文半径.(回文串长度为奇数,即a[i]!=’#’);p[i]/2的值为新串中以i为中心的回文半径(回文串长度为偶数,即a[i]==’#’&&p[i]!=1)
2.比如当前回文串的中间位置是i(回文串是奇数的情况,偶数同理),p[i]表示Manacher求得的延伸半径。那么[i-p[i]+1, i+p[i]-1]就是回文串,故val[1][i+p[i]-1]就该加上i-p[i]+1;而[i-p[i]+2, i+p[i]-2]也是回文串,val[1][i+p[i]-2]就该加上i-p[i]+2…………总之可以知道这个就相当于,对于val[1]数组要在[i, i+p[i]-1]区间上依次加上一个末项为i-p[i]+1且公差为-1的等差数列,val[0]也是同理的这儿同样就不说了。
2.接下来的问题就是如何对对区间更新,让区间[L,R]加上一个首项k公差-1的等差数列。想到了加标记addtag表示加多少。上述问题就转化为addtag[L]+=k;addtag[L+1]+=addtag[L]-1; 考虑到多个区间修改有叠加,开addcnt表示各个点有多少个加操作。所以addtag[L+1]+=addtag[L]-addcnt[L];addcnt[L+1]+=addcnt[L];有余这样的传递会一直传递到数组尾巴,相当于更新了[L,MAXN]区间,所以要减去[R+1,MAXN]区间的(显然也是一个等差数列)。于是用subtag和subcnt表示.处理方式同addtag和addcnt
输入:
aaa
abc
输出:
14
8
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <cstring>
#include <string>
#include <algorithm>
using namespace std;
const int maxn=1111111;
const int mod=1000000007;
char s[maxn<<1];
int p[maxn<<1];//p[i]存放以i为中心最长的回文串长度+1
void manacher()
{
int mx=0,id;
for(int i=1;s[i];i++)
{
if(mx>i)
p[i]=min(p[2*id-1],mx-1);
else
p[i]=1;
for(;s[i+p[i]]==s[i-p[i]];++p[i]);
if(p[i]+i>mx)
{
mx=p[i]+1;
id=1;
}
}
}
char str[maxn];
long long val[2][maxn];//val[0][i]代表以i起始的回文串的结尾位置的和,val[1][i]表示以i结尾的回文串的起始位置的和
long long addtag[2][maxn],addcnt[2][maxn],subtag[2][maxn],subcnt[2][maxn];
void update(int flag,int l,int r,int k)//flag为0处理val[0],为1处理val[1];
{
addtag[flag][l]+=k;
addtag[flag][l]%=mod;
++addcnt[flag][l];
subtag[flag][r+1]+=k-r+l;
subtag[flag][r+1]%=mod;
++subcnt[flag][r];
}
void pushdown()
{
for(int i=1;str[i];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))
{
s[0]='$';
int i=1;
for(;str[i];i++)
{
s[(i<<1)-1]='#';
s[i<<1]=str[i];
}
s[(i<<1)-1]='#';
s[i<<1]=0;
manacher();
// for(int i=1;s[i];i++)
// cout<<p[i]<<" "<<s[i]<<endl;
memset(val,0,sizeof(val));
memset(addtag,0,sizeof(addtag));
memset(addcnt,0,sizeof(addcnt));
memset(subtag,0,sizeof(subtag));
memset(subcnt,0,sizeof(subcnt));
for(int i=1;s[i];i++)
{
if(i&1){//处理回文串长度为偶数的情况
// cout<<s[i]<<endl;
if(p[i]/2==0)
continue;
update(0, i/2-p[i]/2+1, i/2, i/2+p[i]/2);
update(1, i/2+1, i/2+p[i]/2, i/2);
}
else{//处理回文串长度为奇数的情况
update(0, i/2-p[i]/2+1, i/2, i/2+p[i]/2-1);
update(1, i/2, i/2+p[i]/2-1, i/2);
}
}
pushdown();
long long ans=0;
for(int i=1;str[i]&&str[i+1];i++){
//cout<<i<<endl;
ans+=val[1][i]*val[0][i+1];
ans%=mod;
}
if(ans<0)
ans+=mod;
printf("%lld\n",ans);
}
}
HDU 5785 Interesting的更多相关文章
- HDU 5785 Interesting manacher + 延迟标记
题意:给你一个串,若里面有两个相邻的没有交集的回文串的话,设为S[i...j] 和 S[j+1...k],对答案的贡献是i*k,就是左端点的值乘上右端点的值. 首先,如果s[x1....j].s[x2 ...
- hdu 3304 Interesting Yang Yui Triangle
hdu 3304 Interesting Yang Yui Triangle 题意: 给出P,N,问第N行的斐波那契数模P不等于0的有多少个? 限制: P < 1000,N <= 10^9 ...
- HDU - 5785:Interesting (回文树,求相邻双回文的乘积)
Alice get a string S. She thinks palindrome string is interesting. Now she wanna know how many three ...
- Interesting HDU - 5785 回文树
题意: 找出所有[i,j]为回文串[j+1,k]也为回文串的i*k乘积之和. 题解: 设sum1[i] 为正着插入,到 i 的所有回文串的起始位置的前缀和,sum2[i] 表示反正插入的前缀和 ans ...
- hdu 2426 Interesting Housing Problem 最大权匹配KM算法
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2426 For any school, it is hard to find a feasible ac ...
- HDU 2426 Interesting Housing Problem(二分图最佳匹配)
http://acm.hdu.edu.cn/showproblem.php?pid=2426 题意:每n个学生和m个房间,现在要为每个学生安排一个房间居住,每个学生对于一些房间有一些满意度,如果满意度 ...
- hdu 2814 Interesting Fibonacci
pid=2814">点击此处就可以传送 hdu 2814 题目大意:就是给你两个函数,一个是F(n) = F(n-1) + F(n-2), F(0) = 0, F(1) = 1; 还有 ...
- HDU 3304 Interesting Yang Yui Triangle lucas定理
输入p n 求杨辉三角的第n+1行不能被p整除的数有多少个 Lucas定理: A.B是非负整数,p是质数.AB写成p进制:A=a[n]a[n-1]...a[0],B=b[n]b[n-1]...b[0] ...
- HDU 2426 Interesting Housing Problem (最大权完美匹配)【KM】
<题目链接> 题目大意: 学校里有n个学生和m个公寓房间,每个学生对一些房间有一些打分,如果分数为正,说明学生喜欢这个房间,若为0,对这个房间保持中立,若为负,则不喜欢这个房间.学生不会住 ...
随机推荐
- 电子设计省赛--DMA与ADC
//2014年4月17日 //2014年6月20日入"未完毕" //2014年6月21日 DMA可实现无需cpu控制中断的传输数据保存. 特别是ADC转换多个通道时要用到. 关键是 ...
- Win8 使用VC6.0调试
Win8.1下无法执行vc++6.0的解决方法 注意 安装过程中最后一步会卡在那里不动,能够直接关闭安装程序,忽略报错. 1 安装完毕后在安装文件夹下找到MSDEV.EXE 而且将 MSDEV.EXE ...
- sharepreference实现记住password功能
SharePreference是用于保存数据用的.主要调用Context.getSharePreferences(String name, int mode)方法来得到SharePrefere ...
- Excel中将时间格式转化成时间戳格式
时间戳转成正常日期的公式:C1=(A1+8*3600)/86400+70*365+19其中A1表示当时的1249488000时间戳数值其中C1就是所需的日期格式,C1单元格属性改成日期格式就可以了.正 ...
- css之background的cover和contain的缩放背景图
对于这两个属性,官网是这样解释的: contain 此时会保持图像的纵横比并将图像缩放成将适合背景定位区域的最大大小. 等比例缩放图象到垂直或者水平其中一项填满区域. cover 此时会保持图像的纵横 ...
- Nginx反向代理匹配部分二级域名或二级目录配置
server { charset utf-; client_max_body_size 128M; # Add index.php to the list if you are using PHP i ...
- (原+转)C++中的const修饰符
const int a; int const a; 这两个写法是等同的,表示a是一个int常量. 简记:const后面是什么就限定什么(因为C++标准规定,const关键字放在类型或变量名之前等价的) ...
- Shell学习之Shift的用法
位置参数可以用shift命令左移.比如shift 3表示原来的$4现在变成$1,原来的$5现在变成$2等等,原来的$1.$2.$3丢弃,$0不移动.不带参数的shift命令相当于shift 1 ...
- 已知要闪回的大致时间使用基于as of scn的闪回查询
基本判断出要恢复误操作的dml的时间可以使用如下的方法进行数据的恢复: example: 一.创建test表 -------create table flashback_asof------ crea ...
- 微信OPENID授权方法
今天搞了下微信授权, 总结了下微信的授权规则与步骤 先来几个关键字 Openid 微信ip(属于唯一指向公众号的id) redirect_uri 授权回调地址 State 回调地址带参数 Appi ...