Palindrome (manacher + Fenwick tree)

topic

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.
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 ABAB and a b c b a b c abcbabc .

Explanation

Because S [1. .3n-2] (n≥2), S [i] = S [2n-i] = S [2n + i-2] (1≤i≤n), can be obtained 1 ~ 2n- 1 is a palindromic sequence, and this sequence is an odd number, the center of symmetry is n. Further to give n ~ 3n-2 palindromic sequence is an odd number, the center of symmetry of 2n-1. To meet these conditions, it is to find the two centers in the given string.
Set a i, j will be described further, since the results of the search string, the conditions required palindromic sequence is an odd (even-series tubes do so). Therefore, use manacher algorithm, first find the growth len array of strings, and then updates the len [i] (even-series and leave) the string, i is represented by the center of the palindrome radius (central point also count) .
Then enumeration wherein each central palindrome i, seeking the answer is in the [i, i + len [i ] -1] , the number of a j, j∈ [i, i + len [i] -1] and j-len [j] ≤i.
For example cbcbcbc, the result is 5, comprising two cbcb, two BCBC, a cbcbcbc. Since the subject of the request length 3n-2, so only 4,7,10 like. But we do not care, we only care about two palindromic center, i j falls within the scope of the right, the left-most j is less than or equal to i. (Correct selected one of i, j, in fact, the string length of the article is 3 * (j-i + 1 ) -2, i j packages can come in the center, i, j as the center and are palindromic, length must be greater than equal to 3 * (j-i + 1 ) -2, so the choice of questions asked 3 * (j-i + 1 ) -2)
we left from the 1 ~ lens j is a subscript into the memory array by vecto j. Then select 1 ~ lens i, can reach 1 ~ i-1 j are already present in the tree array choice of i, we just like to find out the contents of the number j on the right boundary of the i right. Then there ans + = query (min (lens , i + len [i] -1)) - query (i); i is a note that is not included because if the case comprising i i == j representative of and not intended to meet the problem, will into a string of ordinary palindrome.
Fenwick tree in which the role is to quickly query range and speed.

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#define maxn 500005
#define ll long long
using namespace std;
ll c[maxn];
int lowbit(int x){
    return x&(-x);
}
void updata(int x, int y, int n){
    int i;
    for(i = x; i <= n; i += lowbit(i))
        c[i] += y;
}
ll query(int x){
    int i;
    ll ans = 0;
    for(i = x; i; i -= lowbit(i))
        ans += c[i];
    return ans;
}
char s[maxn], str[maxn*2];
int lens;
void inint(char *s){
    int i;
    str[0] ='@';
    for(i = 1; i <= lens*2; i += 2){
        str[i] ='#';
        str[i+1] =s[i/2];
    }
    str[2*lens+1] = '#';
    str[2*lens+2] = '$';
}
int len[500005*2];
void manacher(int n){
    int i, po = 0, mx = 0;
    for(i = 1; i <= n; i++){
        if(mx > i)
            len[i] = min(mx-i, len[2*po-i]);
        else
            len[i] = 1;
        while(str[i-len[i]] == str[i+len[i]])
            len[i]++;
        if(i+len[i] > mx){
            mx = i+len[i];
            po = i;
        }
    }
}
vector<int> a[500005];
int main(){
    int t, i, j;

    scanf("%d", &t);
    while(t--){
        ll ans = 0;
        scanf("%s", s);
        memset(c, 0, sizeof(c));
        lens = strlen(s);
        inint(s);
        manacher(lens*2+1);
        for(i = 2; i <= lens*2; i += 2) len[i/2] = len[i]/2;
        for(i = 1; i <= lens; i++) a[i].clear();
        for(i = 1; i <= lens; i++) a[i-len[i]+1].push_back(i);
        for(i = 1; i <= lens; i++){
            for(j = 0; j < a[i].size(); j++)
                updata(a[i][j], 1 , lens);
            ans += query(min(lens, i+len[i]-1)) - query(i);
        }
        printf("%lld\n", ans);
    }

    return 0;
}
发布了52 篇原创文章 · 获赞 2 · 访问量 895

Guess you like

Origin blog.csdn.net/qq_44714572/article/details/97617877