题意 : 给定一个字符串S,问你有多少长度为 n 的子串满足  S[i]=S[2n−i]=S[2n+i−2] (1≤i≤n)

参考自 ==> 博客

分析 : 可以看出满足题目要求的特殊回文子串其实是根据 n 以及 2*n-1 对称的,如图所示

如果我设第一个对称点为 i 第二个为 j ,p[i] 为以 i 为中心是回文半径, 那满足题目条件的子串必定满足  j − p[j] + 1 ≤ i < j ≤ i + p[i] − 1

简单点说就是两点的回文半径要相互覆盖

p[]数组很容易使用 Manacher 算法算出来,那么该如何去找答案?(当时就是想到马拉车,然后完全不知道怎么快速找答案,我好菜啊!)

我们从小到大枚举 j , 对于它左边的所有的点找出满足条件的 i ,即 i + p[i] >= j ,那么我哪知道 j 左边的哪些点是能够成为满足条件的 i ?

由于是从小到大更新,我们将枚举过的 j 装进一个根据 j + p[j] 长度升序的优先队列中,然后使用树状数组在 j 这个点更新贡献 + 1

在枚举下一个 j 的时候,我们将优先队列里面的元素一个个取出来(优先队列里面的元素其实就是现在 j 左边的点),取出来有我们需要去掉不满足条件的点 即 覆盖不到当前 j 的点,直到队头点满足条件或者队列为空,然后对于枚举的每一个 j 贡献出来的答案就是树状数组的前缀和 sun(i) - sum(i-p[i]-1)

可能说的不太清楚,具体看看代码吧,看完了应该就懂了!

#include<bits/stdc++.h>
#define lowbit(i) (i&(-i))
using namespace std;
 + ;
];
], id, mx=;
int c[maxn];

int Init()
{
    int len = strlen(s);
    sNew[] = '$';
    sNew[] = '#';
    ;
    ; i < len; i++){
        sNew[j++] = s[i];
        sNew[j++] = '#';
    }
    sNew[j] = '\0';
    return j;
}

int Manacher()
{
    int len = Init();
    ;
    mx = ;
    ; i < len; i++){
         * id - i], mx - i);
        ;

        while (sNew[i - p[i]] == sNew[i + p[i]]) p[i]++;

        if (mx < i + p[i]){
            id = i;
            mx = i + p[i];
        }
    }
    return len;
}

inline void add(int i, int val)
{
    ){
        c[i] += val;
        i += lowbit(i);
    }
}

int sum(int i)
{
    ;
    ){
        ret += c[i];
        i -= lowbit(i);
    }
    return ret;
}

struct cmp{
    bool operator () (int &A, int &B) const{
        return A + p[A] > B + p[B];
    };
};
priority_queue<int, vector<int>, cmp> que;

int main(void)
{
    int nCase;
    scanf("%d\n", &nCase);
    while(nCase--){
        scanf("%s", s);
        int len =  Manacher();

        , j=; j<len; i++,j+=)
            p[i] = p[j]/ - ;

        while(!que.empty()) que.pop();
        memset(c, , sizeof(c));
        ;
        ; i<=(len-)/; i++){
           // printf("%d ", p[i]);
            while(!que.empty()){
                int now = que.top();
                if(now + p[now] < i){///去掉不合格的点!
                    add(now, -);
                    que.pop();
                }else break;
            }
            ans += sum(i) - sum(i-p[i]-);
            que.push(i);
            add(i, );
        }//puts("");
        printf("%lld\n", ans);
    }
    ;
}

瞎 : 马拉车的 p[ ] 数组还有几个特性!

p[i]-1 为以 i 为中心的回文长度

p[i]/2 表示回文半径

i%2==0 表示这个位置为字符,i/2-1 表示原字符串的位置

i%2==1 表示为字符中间,这两边的字符在原字符串的位置分别为 i/2-1 和 i/2

HDU 6230 Palindrome ( Manacher && 树状数组)的更多相关文章

  1. hdu6230 Palindrome(manacher+树状数组)

    题目链接: Palindrome Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Other ...

  2. HDU 3333 | Codeforces 703D 树状数组、离散化

    HDU 3333:http://acm.hdu.edu.cn/showproblem.php?pid=3333 这两个题是类似的,都是离线处理查询,对每次查询的区间的右端点进行排序.这里我们需要离散化 ...

  3. 【BZOJ-3790】神奇项链 Manacher + 树状数组(奇葩) + DP

    3790: 神奇项链 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 304  Solved: 150[Submit][Status][Discuss] ...

  4. HDU 3333 - Turing Tree (树状数组+离线处理+哈希+贪心)

    题意:给一个数组,每次查询输出区间内不重复数字的和. 这是3xian教主的题. 用前缀和的思想可以轻易求得区间的和,但是对于重复数字这点很难处理.在线很难下手,考虑离线处理. 将所有查询区间从右端点由 ...

  5. HDU 3333 Turing Tree (树状数组)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3333 题意就是询问区间不同数字的和. 比较经典的树状数组应用. //#pragma comment(l ...

  6. HDU 4325 Flowers(树状数组+离散化)

    http://acm.hdu.edu.cn/showproblem.php?pid=4325 题意:给出n个区间和m个询问,每个询问为一个x,问有多少个区间包含了x. 思路: 因为数据量比较多,所以需 ...

  7. hdu 5775 Bubble Sort 树状数组

    Bubble Sort 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5775 Description P is a permutation of t ...

  8. 【bzoj2565】最长双回文串 Manacher+树状数组

    原文地址:http://www.cnblogs.com/GXZlegend/p/6802558.html 题目描述 顺序和逆序读起来完全一样的串叫做回文串.比如acbca是回文串,而abc不是(abc ...

  9. HDU - 1541 Stars 【树状数组】

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1541 题意 求每个等级的星星有多少个 当前这个星星的左下角 有多少个 星星 它的等级就是多少 和它同一 ...

随机推荐

  1. 2.转发。基于itchat的微信消息同步机器人

    原文:https://www.jianshu.com/p/7aeadca0c9bd# 看到了该网址有基于itchat的微信消息同步机器人,转过来继续研究.以下是转过来的: 最近 全栈数据工程师养成攻略 ...

  2. 嵌套的frame

    自动化的测试中,iframe的嵌套也是很常见的,对于嵌套的iframe,我们处理的方式是先进入到iframe的父节点, 再进入到子节点,然后可以对子节点里面的对象进行处理和操作.如下的html代码效果 ...

  3. Java多线程学习——任务定时调度

    Timer 本身就是一个线程,最主要的方法就是schedule(). schedule()的参数介绍: schedule(TimerTask task, long delay) //延迟delay毫秒 ...

  4. kafka producer发送消息 Failed to update metadata after问题

    提示示例: ERROR Error when sending message to topic test with key: null, value: 2 bytes with error: Fail ...

  5. Comet OJ C1076 [Contest #4]求和

    题目 首先我们可以通过经典容斥转化为计算\([1,x]\)的答案. 现在我们考虑一个数的个位对答案的贡献. 每做一次操作都会让个位加上十位然后取模,直到只有个位为止. 我们发现这个过程中,个位数前的系 ...

  6. Python和Js打印心形

    看到一行Python写的代码,会用LovePython输出心形: print('\n'.join([''.join([('LovePython'[(x-y)%10]if((x*0.05)**2+(y* ...

  7. [CodePlus 2018 3 月赛] 博弈论与概率统计

    link 题意简述 小 $A$ 与小 $B$ 在玩游戏,已知小 $A$ 赢 $n$ 局,小 $B$ 赢 $m$ 局,没有平局情况,且赢加一分,输减一分,而若只有 $0$ 分仍输不扣分. 已知小 $A$ ...

  8. 二: Jvm内存模型

    因为每个对象生命周期不一样,jvm在做内存管理的时候,就帮我们分成了三个区域: 1.  新生代(回收频率高)   新生和老年默认大小比例为1:2 2.  老年代(回收频率低)     最好所有的对象都 ...

  9. 使用css3的repeating-linear-gradient画虚线

    还在用 border-style: dashed 画虚线吗?虽然也是虚线,但是不能控制每一个虚线的宽度 .dashed { height: 1px; background-image: repeati ...

  10. Elastic Search安装-windows

    转载自:https://blog.csdn.net/linkkb/article/details/82805145 其中稍作修改 ElasticSearch介绍 ES是一个基于Lucene的分布式全文 ...