HDU-6230:Palindrome(manacher+树状数组)

版权声明:http://blog.csdn.net/Mitsuha_。 https://blog.csdn.net/Mitsuha_/article/details/82118798

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

In the example input, there are two substrings which are one-and-half palindromic strings, a b a b and a b c b a b c .

思路:先在纸上画出长度为4,7,10,13的one-and-half palindromic。
很容易就发现这是什么东东了。

先求出字符串的 l e n 数组, l e n [ i ] 表示以 i 为中心的回文半径。

那么枚举其中一个回文中心 i ,则答案求的是在 [ i i + l e n [ i ] 1 ] 中,有多少个 j j [ i , i + l e n [ i ] 1 ] j l e n [ j ] i

其中 l e n 数组可以用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;
}

猜你喜欢

转载自blog.csdn.net/Mitsuha_/article/details/82118798
今日推荐