题目:

大概说给一个字符串,找到其所有子串[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的更多相关文章

  1. HDU 5785 Interesting manacher + 延迟标记

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

  2. hdu 3304 Interesting Yang Yui Triangle

    hdu 3304 Interesting Yang Yui Triangle 题意: 给出P,N,问第N行的斐波那契数模P不等于0的有多少个? 限制: P < 1000,N <= 10^9 ...

  3. HDU - 5785:Interesting (回文树,求相邻双回文的乘积)

    Alice get a string S. She thinks palindrome string is interesting. Now she wanna know how many three ...

  4. Interesting HDU - 5785 回文树

    题意: 找出所有[i,j]为回文串[j+1,k]也为回文串的i*k乘积之和. 题解: 设sum1[i] 为正着插入,到 i 的所有回文串的起始位置的前缀和,sum2[i] 表示反正插入的前缀和 ans ...

  5. 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 ...

  6. HDU 2426 Interesting Housing Problem(二分图最佳匹配)

    http://acm.hdu.edu.cn/showproblem.php?pid=2426 题意:每n个学生和m个房间,现在要为每个学生安排一个房间居住,每个学生对于一些房间有一些满意度,如果满意度 ...

  7. hdu 2814 Interesting Fibonacci

    pid=2814">点击此处就可以传送 hdu 2814 题目大意:就是给你两个函数,一个是F(n) = F(n-1) + F(n-2), F(0) = 0, F(1) = 1; 还有 ...

  8. 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] ...

  9. HDU 2426 Interesting Housing Problem (最大权完美匹配)【KM】

    <题目链接> 题目大意: 学校里有n个学生和m个公寓房间,每个学生对一些房间有一些打分,如果分数为正,说明学生喜欢这个房间,若为0,对这个房间保持中立,若为负,则不喜欢这个房间.学生不会住 ...

随机推荐

  1. Mock.js:前后端分离开发工具

    概述 Mock.js实现的功能 基于 数据模板 生成数据 基于 HTML模板 生成数据 拦截并模拟 Ajax请求 用法 浏览器: <!-- (必选)加载 Mock --> <scri ...

  2. 转:C#整数三种强制类型转换int、Convert.ToInt32()、int.Parse()的区别

    1.int适合简单数据类型之间的转换,C#的默认整型是int32(不支持bool型); 2.int.Parse(string sParameter)是个构造函数,参数类型只支持string类型; 3. ...

  3. 手把手教你使用Git(转)

    Git使用教程 2014-10-25 14:29 by 云溪0707, 10532 阅读, ... 评论, 收藏, 编辑 Git使用教程 一:Git是什么? Git是目前世界上最先进的分布式版本控制系 ...

  4. Centos7安装JDK

    以下是gz包方式: 1,将jdk-8u51-linux-x64.tar.gz放到/usr/java目录下 2,用tar -zxvf jdk-8u51-linux-x64.tar.gz 解压到当前目录 ...

  5. webStorm 列编辑

    webStorm可以像Sublime一样使用列编辑,只是区别在于webStorm只可以编辑连续列表. 按住alt键鼠标选择一列,然后输入文字就会编辑多行,这个功能很赞,比较实用

  6. Android PorterDuff.Mode

    1.PorterDuff.Mode.CLEAR所绘制不会提交到画布上. 2.PorterDuff.Mode.SRC显示上层绘制图片 3.PorterDuff.Mode.DST显示下层绘制图片 4.Po ...

  7. 映射 SQL 和 Java 类型

    http://alex2009.blog.51cto.com/749524/272942 AJAX: http://www.w3school.com.cn/jquery/ajax_ajax.asp h ...

  8. android HttpGet 另开线程获取网络数据问题

    android跨线程通讯可以使用android.os.Handler-android.os.Message这两类对象完成. public static void getResultForHttpGet ...

  9. mini2440 uboot使用nfs方式引导内核,文件系统

    mini2440 uboot使用nfs方式引导内核,文件系统 成于坚持,败于止步 看了一段时间的u-boot了,到今天才真正完全实现u-boot引导内核和文件系统,顺利开机,在此记录完整过程 1.首先 ...

  10. boost::asio 使用 libcurl

    curl 使用 asio 的官方样例 http://curl.haxx.se/libcurl/c/asiohiper.html, 但这个例子用起来有很明细的 bug,asio 异步IO 只注册一次,也 ...