Palindrome 字符串马拉车+树状数组 HDU6230

Palindrome
题面: 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.
题意: 给你一个字符串问你符合题目要求的子串有多少个
思路: 首先我们可以用马拉车求出以每个位置为中心的回文串长度的一半,要符合要求需要两个回文串中心位置 i > j , i − p [ i ] < = j i > j, i-p[i] <=j i>j,ip[i]<=j,所以我们可以用树状数组进行维护,求出总和

#include
using namespace std;
typedef long long ll;
const int N=5e5+5;
char s[N],Ma[N*2];
int mp[N*2],tree[N];
int p[N];
vector<int>t[N];
int len,l;

void add(int x,int v)
{
    while(x<=len)
    {
        tree[x]+=v;
        x+=(x & -x);
    }
}

int sum(int x)
{
    int res=0;
    while(x>0)
    {
        res+=tree[x];
        x-=(x & -x);
    }
    return res;
}

void Mana()
{
    l=0;
    Ma[l++]='$';
    Ma[l++]='#';
    for(int i=0;i<len;i++)
    {
        Ma[l++]=s[i];
        Ma[l++]='#';
    }
    Ma[l++]='\0';
    int mx=0,id=0;
    for(int i=0;i<l;i++)
    {
        mp[i]=mx>i?min(mp[2*id-i],mx-i):1;
        while(Ma[i+mp[i]]==Ma[i-mp[i]])mp[i]++;
        if(i+mp[i]>mx)
        {
            mx=i+mp[i];
            id=i;
        }
    }
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%s",s);
        len=strlen(s);
        memset(tree,0,sizeof tree);
        for(int i=0;i<=len;i++)
            t[i].clear();
        Mana();
        int cnt=1;
        for(int i=2;i<l;i+=2)
        {
            p[cnt]=mp[i]/2-1;
            t[cnt-p[cnt]].push_back(cnt);
            cnt++;
        }
        ll ans=0;
        for(int i=1;i<=len;i++)
        {
            for(int j=0;j<t[i].size();j++)
            {
                add(t[i][j],1);
            }
            ans+=sum(min(i+p[i],len))-sum(i);
        }
        printf("%lld\n",ans);
    }
    return  0;
}

你可能感兴趣的:(字符串-马拉车,树状数组)