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..3n2](n2) is one-and-half palindromic if and only if it satisfies  S[i]=S[2ni]=S[2n+i2](1in).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);
    }
}