Palindrome
Time Limit: 6000/3000 MS (Java/Others)
Memory Limit: 262144/262144 K (Java/Others)
Problem Description
Alice like strings, especially long strings. For each string, she has a special evaluation system to judge how elegant the string is. She defines that a string
is one-and-half palindromic if and only if it satisfies
.For example, abcbabc is one-and-half palindromic string, and abccbaabc is not. Now, Alice has generated some long strings. She ask for your help to find how many substrings which is one-and-half palindromic.
Input
The first line is the number of test cases. For each test case, there is only one line containing a string(the length of strings is less than or equal to 500000), this string only consists of lowercase letters.
Output
For each test case, output a integer donating the number of one-and-half palindromic substrings.
Sample Input
1
ababcbabccbaabc
Sample Output
2
Hint
In the example input, there are two substrings which are one-and-half palindromic strings, and .
思路:先在纸上画出长度为4,7,10,13的one-and-half palindromic。
很容易就发现这是什么东东了。
先求出字符串的 数组, 表示以 为中心的回文半径。
那么枚举其中一个回文中心 ,则答案求的是在 中,有多少个 且 。
其中
数组可以用manacher算法求出。
统计答案可以用树状数组或主席树。
#include<bits/stdc++.h>
using namespace std;
const int MAX=1e6+10;
const int MOD=1e9+7;
const double PI=acos(-1.0);
typedef long long ll;
char s[MAX],p[MAX];
int init(char *str)
{
int n=strlen(str);
for(int i=1,j=0;i<=2*n;i+=2,j++)
{
s[i]='#';
s[i+1]=str[j];
}
s[0]='@';
s[2*n+1]='#';
s[2*n+2]='&';
s[2*n+3]='\0';
return 2*n+1;
}
int len[MAX];
void manacher(int n)
{
int mx=0,p=0;
for(int i=1;i<=n;i++)
{
if(mx>i)len[i]=min(mx-i,len[2*p-i]);
else len[i]=1;
while(s[i-len[i]]==s[i+len[i]])len[i]++;
if(len[i]+i>mx)mx=len[i]+i,p=i;
}
}
ll BIT[MAX];
void add(int x,int y,int n){while(x<=n){BIT[x]+=y;x+=x&(-x);}}
ll ask(int x){ll ans=0;while(x){ans+=BIT[x];x-=x&(-x);}return ans;}
vector<int>e[MAX];
int main()
{
int T;
cin>>T;
while(T--)
{
scanf("%s",p);
int n=init(p);
manacher(n);
for(int i=2;i<=n;i+=2)len[i/2]=len[i]/2;
n/=2;
ll ans=0;
for(int i=1;i<=n;i++)e[i].clear();
for(int i=1;i<=n;i++)BIT[i]=0;
for(int i=1;i<=n;i++)e[i-len[i]+1].push_back(i);
for(int i=1;i<=n;i++)
{
for(int j=0;j<e[i].size();j++)add(e[i][j],1,n);
ans+=ask(min(n,i+len[i]-1))-ask(i);
}
printf("%lld\n",ans);
}
return 0;
}