题意 : 给定一个字符串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. 【MM系列】SAP 簇表 A017 物料信息记录 (指定工厂) 包含的透明表

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[MM系列]SAP 簇表 A017 物料信息记录 ...

  2. 社工 - By源码托管平台|云盘 - GitHub - 汇总

    搜索规则 ()默认搜索是从master分支搜索代码 ()只有小于384k的代码才是可以搜索到的 ()搜索语句不能有特殊字符如. , : ; / \ ` ' " = * ! ? # $ &am ...

  3. (转载)深入解析String#intern

    本文转载自:深入解析String#intern 引言 在 JAVA 语言中有8中基本类型和一种比较特殊的类型String.这些类型为了使他们在运行过程中速度更快,更节省内存,都提供了一种常量池的概念. ...

  4. 深入理解java:1.3.1 JVM内存区域的划分(运行时数据区)

    学习Java GC机制,可以帮助我们在日常工作中 排查各种内存溢出或泄露问题,解决性能瓶颈,达到更高的并发量,写出更高效的程序. 我们将从4个方面学习Java GC机制, 1,内存是如何分配的: 2, ...

  5. 20191127 Spring Boot官方文档学习(4.12)

    4.12.缓存(Caching) Spring框架提供了对应用程序透明添加缓存的支持.从本质上讲,抽象将缓存应用于方法,从而根据缓存中可用的信息减少执行次数.缓存逻辑是透明应用的,不会对调用者造成任何 ...

  6. python+selenium上传文件——input标签

    我们要区分出上传按钮的种类,大体上可以分为两种: 第一种普通上传:将本地文件路径作为一个值,放在input标签中,通过form表单将这个值提交给服务器: 第二种插件上传:是通过Flash.JavaSc ...

  7. 第十七周周总结 Swing

    考试系统 1.登录功能 用户和密码存在在哪里? 文件 2.考试功能 考试题目和答案存在哪? 文件 3.展示功能 GUI Graphical User Interface图形用户接口 #GUI Java ...

  8. [Git] 025 标签命令

    0. 前言 小时候看<剑花-烟雨-江南>,惊讶于那个多重身份的"小侯爷" 后来发现,现实中拥有比小侯爷更多身份的人多如牛毛 其实,在 "Git" 中 ...

  9. 【官网】2019.5.19 CentOS8.0 最新进展

    Contents CentOS 8 Rough Status Page General Steps Architectures Main architectures AltArch Current T ...

  10. thinkphp整合Ueditor编辑器

    编辑器下载地址:http://ueditor.baidu.com/website/download.html#ueditor 放在项目Public或者入口同级目录均可. 前台代码 <div cl ...