2017 CCPC 哈尔滨 A (hdu 6230) Palindrome (Manacher + BIT)

解题思路:   

题目中要求的回文串大致为  ______ i ____ j ______  分别以 i j 为中心的两个回文串

我们可以使用Manacher算法先处理出以每个字符为中心的回文串的长度,注意这里求出来的回文串长度一定都是奇数

然后我们令 p[i] 为以第 i 个字符为中心的回文半径

然后一个字符串想要满足题意需要满足下面三个条件

j > i
j-i <= p[i]
j-i <= p[j]

我们可以把最后一个式子移项  得到 i >= j - p[j]  ①

所以我们可以每次把 满足①条件的 j 放入树状数组中,然后每次求在 ( i  , i+p[i] ] 范围内的j有多少


AC代码:

/*
* @Author: wchhlbt
* @Last Modified time: 2017-11-12
*/

#include 

#define inf 0x3f3f3f3f
#define pb push_back
#define AA first
#define BB second
#define ONES(x) __builtin_popcount(x)
#define _  << " " <<
using namespace std;

typedef pair P;
typedef long long ll ;
int dx[4] = {0,0,1,-1};
int dy[4] = {1,-1,0,0};
const double eps =1e-3;
const int mod = 1000000007;
const double PI = acos(-1.0);
inline int read(){ int num;    scanf("%d",&num);   return num;}
const int maxn = 500007;

char Ma[maxn*2];
int Mp[maxn*2];
int Manacher(char s[],int len)
{
    int l = 0;
    Ma[l++] = '$';
    Ma[l++] = '#';
    for(int i = 0; ii ? min(Mp[2*id-i],mx-i) : 1;
        while(i-Mp[i]>=0 && Ma[i+Mp[i]]==Ma[i-Mp[i]]) Mp[i]++;
        if(i+Mp[i]>mx)
        {
            mx=i+Mp[i];
            id=i;
        }
    }
    return l;
}

char s[maxn];
int p[maxn];
vector g[maxn];

//BIT 向下统计 向上修改
int bit[maxn];
int n;
int sum(int i)
{
    int s = 0;
    while(i>0){
        s += bit[i];
        i -= i & -i;
    }
    return s;
}

void add(int i, int x)//i 不能取 0
{
    while(i<=n){
        bit[i] += x;
        i += i&-i;
    }
}

int main()
{
    int t = read();
    while(t--){
        //init
        memset(bit,0,sizeof bit);
        for(int i = 0; i


你可能感兴趣的:(HDU,数据结构,字符串)