hdu6230 Palindrome(manacher+树状数组)

题目链接:

Palindrome

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 113    Accepted Submission(s): 44


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
1 ababcbabccbaabc
 

 

Sample Output
2
 
题意:问题目描述的字串有多少个?
 
思路:可以发现这种字符串是关于S[n]和S[2n-1]对称的,所以枚举S[2n-1],看在S[2n-1]的半径范围内有多少个S[n]的半径范围包括S[2n-1],可以manacher找到半径,然后树状数组求答案;
 
AC代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn=5e5+10;
char s[maxn];
int r[maxn],sum[maxn],n;
struct cmp
{
    bool operator()(int x,int y)
    {
        return x+r[x]>y+r[y];
    }
};
priority_queue<int,vector<int>,cmp>qu;
inline int lowbit(int x){return x&(-x);}
inline void update(int x,int num)
{
    while(x<=n)
    {
        sum[x]+=num;
        x+=lowbit(x);
    }
    return ;
}
inline int query(int x)
{
    int ans=0;
    while(x)
    {
        ans+=sum[x];
        x-=lowbit(x);
    }
    return ans;
}
int main()
{
    int T;scanf("%d ",&T);
    while(T--)
    {
        gets(s);
        n=strlen(s);
        for(int i=n;i>0;i--)s[i]=s[i-1],sum[i]=0;
        s[0]='#';s[n+1]='\n';
        int mx=0,id=0;
        for(int i=1;i<=n;i++)
        {
            if(mx>i)r[i]=(r[2*id-i]<(mx-i)?r[2*id-i]:(mx-i));
            else r[i]=1;
            while(s[i-r[i]]==s[i+r[i]])r[i]++;
            if(i+r[i]>mx)mx=i+r[i],id=i;
        }
        for(int i=1;i<=n;i++)r[i]--;
        LL ans=0;int num=0;
        while(!qu.empty())qu.pop();
        qu.push(1);update(1,1);num++;
        for(int i=2;i<=n;i++)
        {
            while(!qu.empty())
            {
                int fr=qu.top();
                if(fr+r[fr]<i)
                {
                    qu.pop();
                    num--;
                    update(fr,-1);
                }
                else break;
            }
            ans=ans+num-query(i-r[i]-1);
            qu.push(i);update(i,1);num++;
        }
        printf("%lld\n",ans);
    }
    return 0;
}

  

posted @ 2017-11-13 18:00  LittlePointer  阅读(566)  评论(0编辑  收藏  举报