[hdu6230]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..3n2](n2)S[1..3n−2](n≥2) is one-and-half palindromic if and only if it satisfies S[i]=S[2ni]=S[2n+i2](1in)S[i]=S[2n−i]=S[2n+i−2](1≤i≤n).For example, abcbabcabcbabc is one-and-half palindromic string, and abccbaabcabccbaabc 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 500000500000), 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, abababab and abcbabcabcbabc.

題意:
輸出字符串s中,"一又一半字符串"的數量
“一又一半字符串” : 字符串S[1..3n2](n2)S[1..3n−2](n≥2),滿足了S[i]=S[2ni]=S[2n+i2](1in)S[i]=S[2n−i]=S[2n+i−2](1≤i≤n)

題解:
很顯然這個字符串是一個奇數長度的字符串。
我們先用馬拉車做出對於每個中點ii的最長迴文串長度的半徑r[i]r[i]
然後很顯然,我們考慮兩個拼在一起的迴文串的中點i,j(i>j)i,j(i>j)
只需要滿足j+r[j]1<=ij+r[j]-1<=iir[i]+1>=ji-r[i]+1>=j
那麼我們把所有ir[i]+1i-r[i]+1相同的ii存在一起
然後枚舉j=ir[i]+1j=i-r[i]+1,把所有的這些ii的樹狀數組位置都+1
然後查詢區間[j,j+r[j]1][j,j+r[j]-1]區間的元素之和。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline int lowbit(int x){return x&(-x);}
char s[500004];
int n,r[500004];
int tr[500004];
vector<int>vec[500004];
ll ans;
void add(int x){
    for(int i=x;i<=n;i+=lowbit(i))tr[i]++;
}
int ask(int x){
    int ret=0;
    for(int i=x;i>0;i-=lowbit(i))ret+=tr[i];
    return ret;
}
int w33ha(){
    ans=0;
    scanf("%s",s);
    n=strlen(s);
    for(int i=0;i<=n;i++)tr[i]=0;
    for(int i=0;i<=n;i++)vec[i].clear();
    for(int i=0;i<n;i++)r[i]=0;
    int mx=0,id=0;
    for(int i=0;i<n;i++){
        r[i]=(mx>i)?min(r[id*2-i],mx-i):1;
        while(i-r[i]>=0&&i+r[i]<n&&s[i-r[i]]==s[i+r[i]])r[i]++;
        if(i+r[i]>mx){
            mx=i+r[i];
            id=i;
        }
    }
    for(int i=n;i>=1;i--)r[i]=r[i-1];
    for(int i=1;i<=n;i++){
        vec[i-r[i]+1].push_back(i);
    }
    for(int i=1;i<=n;i++){
        for(int j=0;j<vec[i].size();j++){
            add(vec[i][j]);
        }
        ans+=ask(i+r[i]-1)-ask(i);
    }
    printf("%lld\n",ans);
    return 0;
}
int main(){
    int T;scanf("%d",&T);
    while(T--)w33ha();
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章