多校1005 HDU5785 Interesting (manacher)

 // 多校1005 HDU5785 Interesting
// 题意:给你一个串,求相邻两个回文串左边端点*右边端点的和
// 思路:马拉车算出最长回文半径,求一个前缀和,既得到每个点对答案的贡献。
// ans=L[i]*R[i-1]
// L[i] 以i开始的所有回文串结尾坐标的和
// R[i] 以i结尾的所有回文串开始坐标的和
// 这题我们关键是求L[] R[]
// 另开两个数组a[] b[] 分别记录当前点对答案贡献 和每个点出现的次数 // #pragma comment(linker, "/STACK:102c000000,102c000000")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <sstream>
#include <string>
#include <algorithm>
#include <list>
#include <map>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <cstdlib>
// #include <conio.h>
using namespace std;
#define clc(a,b) memset(a,b,sizeof(a))
#define inf 0x3f3f3f3f
#define lson l,mid,rt<<1
// #define rson mid+1,r,rt<<1|1
const int N = 1e6+;
const int MOD = 1e9+;
#define LL long long
#define LB long double
// #define mi() (l+r)>>1
double const pi = acos(-);
const double eps = 1e-;
void fre(){freopen("in.txt","r",stdin);}
inline int read(){int x=,f=;char ch=getchar();while(ch>''||ch<'') {if(ch=='-') f=-;ch=getchar();}while(ch>=''&&ch<='') { x=x*+ch-'';ch=getchar();}return x*f;} char str[N];
char s[N<<];
int Len[N<<];
void Manacher(int n){
clc(s,'#');
for(int i=;i<n;i++)
s[i*+]=str[i];
int len=n*+;s[]='$';
int mx=,po=;
for(int i=;i<=len;i++) {
if(mx>i)
Len[i]=min(Len[po*-i],mx-i);
else Len[i]=;
while(s[i+Len[i]]==s[i-Len[i]]) Len[i]++;
if(i+Len[i]>mx) { mx=i+Len[i];po=i;}
}
} LL a[N<<],b[N<<];
LL L[N],R[N];
int main(){
while(~scanf("%s",str)){
int len=strlen(str);
Manacher(len);
len=(len<<)+;
for(int i=;i<=len;i++) a[i]=,b[i]=;
for(int i=len;i>=;i--){
a[i-Len[i]+]+=i;
a[i+]-=i;
b[i-Len[i]+]++;
b[i+]--;
}
LL a1=,a2=;
for(int i=;i<=len;i++){
a1+=a[i],a2+=b[i];
if(i%==)
L[i/]=(a1-a2*i/)%MOD;
} for(int i=;i<=len;i++) a[i]=,b[i]=;
a1=,a2=;
for(int i=len;i>=;i--){
a[i]+=i;
a[i+Len[i]]-=i;
b[i]++;
b[i+Len[i]]--;
}
for(int i=;i<=len;i++){
a1+=a[i],a2+=b[i];
if(i%==)
R[i/]=(a1-a2*i/)%MOD;
} LL ans=;
for(int i=;i<=len/;i++){
ans=(ans+L[i]*R[i-]%MOD)%MOD;
}
printf("%I64d\n",ans);
}
return ;
}
上一篇:Django form表单


下一篇:测试图形验证码接口