• 【洛谷 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;
    }
    
    
  • 相关阅读:
    重置(reset) HANA的是system的密码
    Linux删除其他程序正在使用的文件
    ECC升级S/4HANA
    一步一步教你写SAP RFC
    如何查看MAXDB日志
    How to delete SAP* from HANA Tenant database(HANA数据库下如何删除SAP*账户)
    echo N>/proc/sys/vm/drop_caches清理缓存
    SUM in the family way
    vue 使用 autoprefixer amfeflexible postcsspxtorem 自动转rem移动端适配
    VueJS实现迷糊查询
  • 原文地址:https://www.cnblogs.com/Qihoo360/p/9743291.html
Copyright © 2020-2023  润新知