Palindrome
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 602 Accepted Submission(s): 234
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
1ababcbabccbaabc
Sample Output
2
Hint
In the example input, there are two substrings which are one-and-half palindromic strings, $abab$ and $abcbabc$. Source
2017中国大学生程序设计竞赛-哈尔滨站-重现赛(感谢哈理工)
题意:
给出一个字符串,求满足条件的子串的个数。条件如图
A和B构成回文串同时,B和C构成回文串。
题解:
先Manacher求出回文半径。
考虑 ________i_________j________,一定有
j>i
i+r[i]>j
j-r[j]<i
当我们枚举i时,就是要求在区间[i+1,i+r[i]-1]中有多少个j满足j-r[j]<i,又我们从小到大枚举i,而满足j-r[j]<i则一定满足j-r[j]<i+1,所以,可以利用树状数组求解。
代码:
#include<bits/stdc++.h>
#define N 500010
#define LL long long
using namespace std;
char s[N],ss[N<<1];
int r[N<<1],len,n,d[N];
vector<int>g[N];
void Manacher()
{
int ll = strlen(s),p,mx=0;
len=2; ss[0] = '$'; ss[1] = '#';
for (int i = 0; i < ll; i++)ss[len++] = s[i],ss[len++] = '#';
ss[len] = '\0';
for (int i = 1; i < len; i++)
{
if (i<mx) r[i]=min(r[2*p-i],mx-i);else r[i] = 1;
while (ss[i-r[i]]==ss[i+r[i]]) r[i]++;
if (mx<i+r[i])p=i,mx=i+r[i];
}
}
void updata(int x,int y)
{
for (int i=x;i<=n;i+=i&-i) d[i]+=y;
}
LL sum(int x)
{
LL t=0; for (int i=x;i;i-=i&-i) t+=d[i]; return t;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%s",s);LL ans=0;
n=strlen(s);memset(r,0,sizeof r);
Manacher();
for (int i=0;i<=n;i++) d[i]=0,g[i].clear();
for (int i=1;i<=n;i++) r[i]=r[i<<1]>>1,g[i-r[i]].push_back(i);
for (int i=1;i<=n;i++)
{
for (int j=0;j<g[i-1].size();j++) updata(g[i-1][j],1);
if (r[i]>1)ans+=sum(i+r[i]-1)-sum(i);
}
printf("%I64d\n",ans);
}
}