zoukankan      html  css  js  c++  java
  • 【洛谷 P4555】 [国家集训队]最长双回文串 (Manacher)

    题目链接
    (|S|<=10^5),时间还是很宽松的。
    允许我们使用线性/(Nlog N)/甚至(N sqrt N)的算法。
    (l[i])表示以(a[i])结尾的最长回文串,(r[i])表示以(a[i])开头的最长的回文串,
    那么答案很显然就是(max_{i=1}^{len-1}l[i]+r[i+1])
    怎么求?
    回顾一下我们的马拉车算法

    for(int i = 1; i < len; ++i){
       if(i < maxright)
         hw[i] = min(hw[(mid << 1) - i], hw[mid] + mid - i);    //min左边的参数是这个点的对称点的hw值,右边的是保证这个部分在这个大回文串之内
       else hw[i] = 1;
       while(a[i + hw[i]] == a[i - hw[i]]) ++hw[i];  //拓展
       if(hw[i] + i > maxright){   //更新右端点
         maxright = hw[i] + i;
         mid = i;
       }
    }
    

    我们在每个(i)处理出(hw[i])后更新(i)~(i+hw[i]-1)(l)值,每个位置只需要更新一次就好了,因为我们是从左到右遍历的,因此第一次更新的一定是最优值。所以我们只需要定义一个变量(p),表示已经更新到哪里了,然后每次(for(p->i+hw[i]-1)),更新(l)值,如果(p)已经超过(i+hw[i]-1),是不会更新的,保证每个位置只被更新一次,也就是保证了时间复杂度是线性的。(r)也同理,反过来跑一遍就好了。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int MAXN = 100010;
    char b[MAXN], a[MAXN << 1];
    int hw[MAXN << 1], l[MAXN], r[MAXN], ans, n, p = 1;
    int main(){
        scanf("%s", b);
        a[0] = a[1] = '#';
        int len = strlen(b);
        for(int i = 0; i < len; ++i)
           a[(i << 1) + 2] = b[i], a[(i << 1) + 3] = '#';
        int maxright = 0, mid; len = (len << 1) + 3;
        for(int i = 1; i < len; ++i){
           if(i < maxright)
             hw[i] = min(hw[(mid << 1) - i], hw[mid] + mid - i);
           else hw[i] = 1;
           while(a[i + hw[i]] == a[i - hw[i]]) ++hw[i];
           if(hw[i] + i > maxright){
             maxright = hw[i] + i;
             mid = i;
           }
           for(; p < i + hw[i]; ++p) l[p] = (p - i) + 1 - (a[p] == '#');
        }p = len - 1;
        for(int i = len - 1; i; --i)
           for(; p > i - hw[i]; --p)
              r[p] = (i - p) + 1 - (a[p] == '#');
        for(int i = 1; i < len - 1; ++i)
           ans = max(ans, l[i] + r[i + 1]); 
        printf("%d
    ", ans);
        return 0;
    }
    
    
  • 相关阅读:
    【BZOJ4383】[POI2015]Pustynia 线段树优化建图
    【BZOJ4519】[Cqoi2016]不同的最小割 最小割树
    【BZOJ2229】[Zjoi2011]最小割 最小割树
    【BZOJ2151】种树 双向链表+堆(模拟费用流)
    Python入门之Pycharm开发中最常用快捷键
    Python Web学习笔记之GIL机制下的鸡肋多线程
    SQL学习之Can't connect to MySQL server on localhost (10061)
    win10锁屏界面无法更新
    如何安装Pycharm官方统计代码行插件
    Notepad++ 主题配色配置
  • 原文地址:https://www.cnblogs.com/Qihoo360/p/9743291.html
Copyright © 2011-2022 走看看