Interesting
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 336 Accepted Submission(s): 117
Problem Description
Alice get a string S. She thinks palindrome string is interesting. Now she wanna know how many three tuple (i,j,k) satisfy
1≤i≤j<k≤length(S)
, S[i..j] and S[j+1..k] are all palindrome strings. It's easy for her. She wants to know the sum of i*k of all required three tuples. She can't solve it. So can you help her? The answer may be very large, please output the answer mod 1000000007.
A palindrome string is a string that is same when the string is read from left to right as when the string is read from right to left.
A palindrome string is a string that is same when the string is read from left to right as when the string is read from right to left.
Input
The input contains multiple test cases.
Each test case contains one string. The length of string is between 1 and 1000000. String only contains lowercase letter.
Each test case contains one string. The length of string is between 1 and 1000000. String only contains lowercase letter.
Output
For each test case output the answer mod 1000000007.
Sample Input
aaa abc
Sample Output
14 8
Author
ZSTU
Source
Recommend
wange2014
题意
给你一个串
定义了一个权值和
每个权值是两个回文串拼起来的左右坐标乘积
做法
一看回文,果断上回文树
由于要两个回文串拼起来,于是想到最长双回文串那个题目
把串正着扫一遍反着扫一遍就可以得到所有的双回文串
这道题目,我在回文树里多维护了,每个节点为结尾位置的所有回文串的长度和
由于num数组有以此为结尾的长度数量,因此可以通过这两个算出以某点结尾的所有回文串起始坐标的和
同理也可算出所有以某点开始的所有回文串结尾坐标的和
于是把这两个分别乘起来加和即可。
不过这个题目用回文树有爆空间的危险,各个细节必须处理的很好才行。中间过程开LL结果保存先取模再存回int
标答用的manacher也可以做类似的维护来算出结果
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
typedef long long LL;
const int MAXN=1e6+5;
const int MO=1e9+7;
const int N=26;
int l[MAXN],l1[MAXN];
struct Palindromic_Tree {
int next[MAXN][N];
int fail[MAXN],len[MAXN],num[MAXN];
char S[MAXN];
int n,p,last;
int newnode(int l)
{
for(int i = 0; i < N; ++i) next[p][i] = 0;
num[p] = 0;
len[p] = l;
return p++;
}
void init()
{
last = n = p = 0;
newnode(0);
newnode(-1);
S[0] = -1;
fail[0] = 1;
fail[1] = 0;
l[0]=0;
l[1]=0;
}
int get_fail(int x)
{
while(S[n-len[x]-1]!=S[n])
x=fail[x];
return x;
}
int add(int c) ///返回新添加的节点
{
c -= 'a';
S[++n] = c;
int cur = get_fail(last);
if(!next[cur][c]) {
int now = newnode(len[cur]+2);
fail[now] = next[get_fail(fail[cur])][c];
//if(fail[now]==0)
// l[now]=1;
//else
l[now]=((LL)l[fail[now]]+len[now])%MO;
next[cur][c] = now;
num[now]=num[fail[now]]+1;
}
last = next[cur][c];
return last;
}
};
Palindromic_Tree T;
char s[MAXN];
int main()
{
while(scanf("%s",s+1)!=EOF)
{
memset(l,0,sizeof(l));
T.init();
int n=strlen(s+1);
for(int i=n;i>=1;--i)
{
int tmp=T.add(s[i]);
//cout<<"l "<<l[tmp]<<" num "<<T.num[tmp]<<endl;
l1[i]=(l[tmp]+(LL)(i-1)*T.num[tmp])%MO;
}
//for(int i=1;i<=n;i++)
// cout<<l1[i]<<" ";
//cout<<endl;
//memccpy(l1,l,sizeof(l));
LL ans=0;
T.init();
memset(l,0,sizeof(l));
for(int i=1;i<n;++i)
{
int tmp=T.add(s[i]);
//cout<<"l "<<l[tmp]<<" num "<<T.num[tmp]<<" "<<(T.num[tmp]*(i+1)-l[tmp])<<endl;
ans=(ans+(((LL)T.num[tmp]*(i+1)-l[tmp])%MO)*l1[i+1]%MO)%MO;
}
printf("%I64d\n",ans);
}
return 0;
}