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,ip[i]<=ji > j, i-p[i] <=j,所以我們可以用樹狀數組進行維護,求出總和

#include<bits/stdc++.h>
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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章