Palindrome
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 313 Accepted Submission(s): 123
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
S[1..3n−2](n≥2)
is one-and-half palindromic if and only if it satisfies
S[i]=S[2n−i]=S[2n+i−2](1≤i≤n)
.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
2HintIn the example input, there are two substrings which are one-and-half palindromic strings, $abab$ and $abcbabc$.
Source
Recommend
jiangzijing2015
题意:给你一个字符串,问其中有多少个子串符合题目中的要求
解题思路:观察可以发现,符合题目要求的子串就是两个回文串构成的,可以先通过Manacher算法求出每个位置的回文半径,并且因为回文串必须是奇数长度的,所以可以不需要添加字符。然后就是要求有多少对i和j,它们的回文半径是可以互相覆盖的到对方的即可,这个可以通过主席树来解决
#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <set>
using namespace std;
const int INF=0x3f3f3f3f;
#define LL long long
const int maxn=5e5+10;
char ch[maxn];
int p[maxn],len,tot;
int s[maxn],L[maxn*40],R[maxn*40];
LL sum[maxn*40];
void update(int &now,int pre,int l,int r,int p)
{
now=++tot,L[now]=L[pre],R[now]=R[pre],sum[now]=sum[pre]+1;
if(l==r) {L[now]=R[now]=0;return ;}
int mid=(l+r)>>1;
if(p<=mid) update(L[now],L[pre],l,mid,p);
else update(R[now],R[pre],mid+1,r,p);
}
LL query(int u,int v,int l,int r,int p)
{
if(l>=p) return sum[v]-sum[u];
int mid=(l+r)>>1;
LL ans=0;
if(p<=mid) ans+=query(L[u],L[v],l,mid,p);
ans+=query(R[u],R[v],mid+1,r,p);
return ans;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%s",ch+1);
len=strlen(ch+1);
ch[0]='#';
memset(p,0,sizeof p);
memset(s,0,sizeof s);
int id=0,ma=0;
LL ans=0;
tot=0;
for(int i=1;i<=len;i++)
{
p[i]=ma>i?min(p[id*2-i],ma-i):1;
while(ch[i+p[i]]==ch[i-p[i]]) p[i]++;
if(i+p[i]>ma)
{
ma=i+p[i];
id=i;
}
}
s[0]=0,sum[0]=0;
for(int i=1;i<=len;i++)
{
if(p[i]!=1) ans+=1LL*query(s[i-p[i]],s[i-1],1,len,i);
update(s[i],s[i-1],1,len,i+p[i]-1);
}
printf("%lld\n",ans);
}
return 0;
}