多校1005 HDU5785 Interesting (manacher)

  1 // 多校1005 HDU5785 Interesting
  2 // 题意:给你一个串,求相邻两个回文串左边端点*右边端点的和
  3 // 思路:马拉车算出最长回文半径,求一个前缀和,既得到每个点对答案的贡献。
  4 // ans=L[i]*R[i-1]
  5 // L[i] 以i开始的所有回文串结尾坐标的和
  6 // R[i] 以i结尾的所有回文串开始坐标的和
  7 // 这题我们关键是求L[] R[]
  8 // 另开两个数组a[] b[] 分别记录当前点对答案贡献 和每个点出现的次数
  9
 10
 11 // #pragma comment(linker, "/STACK:102c000000,102c000000")
 12 #include <iostream>
 13 #include <cstdio>
 14 #include <cstring>
 15 #include <sstream>
 16 #include <string>
 17 #include <algorithm>
 18 #include <list>
 19 #include <map>
 20 #include <vector>
 21 #include <queue>
 22 #include <stack>
 23 #include <cmath>
 24 #include <cstdlib>
 25 // #include <conio.h>
 26 using namespace std;
 27 #define clc(a,b) memset(a,b,sizeof(a))
 28 #define inf 0x3f3f3f3f
 29 #define lson l,mid,rt<<1
 30 // #define rson mid+1,r,rt<<1|1
 31 const int N = 1e6+10;
 32 const int MOD = 1e9+7;
 33 #define LL long long
 34 #define LB long double
 35 // #define mi() (l+r)>>1
 36 double const pi = acos(-1);
 37 const double eps = 1e-8;
 38 void fre(){freopen("in.txt","r",stdin);}
 39 inline int read(){int x=0,f=1;char ch=getchar();while(ch>‘9‘||ch<‘0‘) {if(ch==‘-‘) f=-1;ch=getchar();}while(ch>=‘0‘&&ch<=‘9‘) { x=x*10+ch-‘0‘;ch=getchar();}return x*f;}
 40
 41 char str[N];
 42 char s[N<<1];
 43 int Len[N<<1];
 44 void Manacher(int n){
 45     clc(s,‘#‘);
 46     for(int i=0;i<n;i++)
 47         s[i*2+2]=str[i];
 48         int len=n*2+1;s[0]=‘$‘;
 49         int mx=0,po=0;
 50         for(int i=1;i<=len;i++)  {
 51             if(mx>i)
 52                 Len[i]=min(Len[po*2-i],mx-i);
 53             else Len[i]=1;
 54             while(s[i+Len[i]]==s[i-Len[i]])  Len[i]++;
 55             if(i+Len[i]>mx) { mx=i+Len[i];po=i;}
 56         }
 57 }
 58
 59 LL a[N<<1],b[N<<1];
 60 LL L[N],R[N];
 61 int main(){
 62     while(~scanf("%s",str)){
 63         int len=strlen(str);
 64         Manacher(len);
 65         len=(len<<1)+1;
 66         for(int i=0;i<=len;i++) a[i]=0,b[i]=0;
 67         for(int i=len;i>=1;i--){
 68             a[i-Len[i]+1]+=i;
 69             a[i+1]-=i;
 70             b[i-Len[i]+1]++;
 71             b[i+1]--;
 72         }
 73         LL a1=0,a2=0;
 74         for(int i=1;i<=len;i++){
 75             a1+=a[i],a2+=b[i];
 76             if(i%2==0)
 77             L[i/2]=(a1-a2*i/2)%MOD;
 78         }
 79
 80         for(int i=0;i<=len;i++) a[i]=0,b[i]=0;
 81         a1=0,a2=0;
 82         for(int i=len;i>=1;i--){
 83             a[i]+=i;
 84             a[i+Len[i]]-=i;
 85             b[i]++;
 86             b[i+Len[i]]--;
 87         }
 88         for(int i=1;i<=len;i++){
 89             a1+=a[i],a2+=b[i];
 90             if(i%2==0)
 91             R[i/2]=(a1-a2*i/2)%MOD;
 92         }
 93
 94         LL ans=0;
 95         for(int i=2;i<=len/2;i++){
 96             ans=(ans+L[i]*R[i-1]%MOD)%MOD;
 97         }
 98         printf("%I64d\n",ans);
 99     }
100     return 0;
101 }
时间: 2024-10-09 08:58:39

多校1005 HDU5785 Interesting (manacher)的相关文章

HDU5785 Interesting(Manacher + 延迟标记)

题目大概说给一个字符串,找到其所有子串[i...k]满足它是由两个回文串拼成的,求Σi*k. 官方题解这么说的: 用manacher算法O(n)求出所有的回文半径.有了回文半径后,就可以求出cntL[i]表示以i结尾的回文串的起始位置的和cntR[i]表示以i起始的回文串的结尾位置的和,然后就可以求出答案了,这里要注意奇偶长度回文串的不同处理.复杂度O(n). 本渣渣看了好久想了好久..才反应过来x1*y1+x1*y2+x2*y1+x2*y2=(x1+x2)*(y1+y2) ..这个真反应不过来

HDU-5785 Interesting(Manacher算法+区间处理)

题目大意:给一个字符串,求所有相邻两回文子串的外侧下标之积的和 题目分析:另L[i]为所有以 i 为右端点的回文字串的左端点之和,同理,另R[i]表示所有以 i 为左端点的回文子串的右端点之和.显然,答案为sigma(L[i]*R[i+1]) 其中,1<=i<length(字符串).求出L和R是关键.先用manacher算法处理出p数组,然后再求出L和R.求L和R的思想(非常巧妙)跟树状数组求区间和的思想差不多.不过,这道题如果用树状数组或线段树的话会超时. 参考代码: # include&l

hdu 5785 Interesting(manacher+前缀和)

题目链接:hdu 5785 Interesting 题意: 有一个长度为n的串(n<=10^6),对 1 <= i <= j < k <= length(s) . 如果[i,j]和[j+1,k]都是回文串.则对答案的贡献为 i*k ,求贡献和. 题解: 详细题解传送门 1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=a;i<=b;++i) 3 using namespace std; 4 type

HDU 5785 Interesting manacher + 延迟标记

题意:给你一个串,若里面有两个相邻的没有交集的回文串的话,设为S[i...j] 和 S[j+1...k],对答案的贡献是i*k,就是左端点的值乘上右端点的值. 首先,如果s[x1....j].s[x2....j].s[x3....j]....s[xn....j].是回文串,而且s[j+1...y1].s[j+1...y2].s[j+1...y3].也是回文串,那么这些串对答案的贡献一共就是(x1+x2+...+xn)*(y1+y2+....+yn) 所以想到了用cntL[i]表示:以i这个字符为

hdu 4901 The Romantic Hero(计数dp)2014多校训练第4场1005

The Romantic Hero                                                                               Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Problem Description There is an old country and the king fell in lov

HDU 5371 (2015多校联合训练赛第七场1003)Hotaru&#39;s problem(manacher+二分/枚举)

HDU 5371 题意: 定义一个序列为N序列:这个序列按分作三部分,第一部分与第三部分相同,第一部分与第二部分对称. 现在给你一个长为n(n<10^5)的序列,求出该序列中N序列的最大长度. 思路: 来自官方题解:修正了一些题解错别字(误 先用求回文串的Manacher算法,求出以第i个点为中心的回文串长度,记录到数组p中 要满足题目所要求的内容,需要使得两个相邻的回文串,共享中间的一部分,也就是说,左边的回文串长度的一半,要大于等于共享部分的长度,右边回文串也是一样. 因为我们已经记录下来以

HDU 5371 (2015多校联合训练赛第七场1003)Hotaru&amp;#39;s problem(manacher+二分/枚举)

pid=5371">HDU 5371 题意: 定义一个序列为N序列:这个序列按分作三部分,第一部分与第三部分同样,第一部分与第二部分对称. 如今给你一个长为n(n<10^5)的序列,求出该序列中N序列的最大长度. 思路: 来自官方题解:修正了一些题解错别字(误 先用求回文串的Manacher算法.求出以第i个点为中心的回文串长度.记录到数组p中 要满足题目所要求的内容.须要使得两个相邻的回文串,共享中间的一部分,也就是说.左边的回文串长度的一半,要大于等于共享部分的长度,右边回文串也

2014多校第七场1005 || HDU 4939 Stupid Tower Defense (DP)

题目链接 题意 :长度n单位,从头走到尾,经过每个单位长度需要花费t秒,有三种塔: 红塔 :经过该塔所在单位时,每秒会受到x点伤害. 绿塔 : 经过该塔所在单位之后的每个单位长度时每秒都会经受y点伤害. 蓝塔 : 经过该塔所在单位之后,再走每个单位长度的时候时间会变成t+z. 思路 : 官方题解 : 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #define LL long long

Hotaru&amp;#39;s problem(hdu5371+Manacher)多校7

Hotaru's problem Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 2274    Accepted Submission(s): 795 Problem Description Hotaru Ichijou recently is addicated to math problems. Now she is playin