• 回文串--Manacher算法(模板)


    用途:在O(n)时间内,求出以每一个点为中心的回文串长度。

    首先,有一个非常巧妙的转化。由于回文串长度有可能为奇数也有可能为偶数,说明回文中心不一定在一个字符上。所以要将字符串做如下处理:在每两个字母之间插入一个特殊字符,通常用“#”,这样所有的回文串就都变成了以一个字符为回文中心的。并且,我们需要在字符串的开头或者结尾插入另一个特殊字符,比如说“*”,防止它无休止地匹配下去。

    变量声明:
    mx:当前已经判断过的能成为回文串的最远长度。比如说如果字符串为bacabaaa,枚举回文中心到c,那么mx应该为5,即b的位置。
    id:mx所对应的回文中心。
    p[i]:以i为中心的回文串向某一边最多延伸的长度。同样是上面那个例子,p[3]=3,p[7]=2,p[1]=1.


    例题:K–弗基桑
    要求:数字序列,求最长回文串长度。
    注意填充的时候要用数列中一定没有出现的字符进行填充。

    #include <iostream>  
    #include <cstring>
    #include <algorithm>  
    using namespace std;
    
    const int maxn = 1e5 + 5;
    int T, n;
    int s[maxn], s_new[2 * maxn-100000];
    int p[2 * maxn-100000];
    
    int init()
    {
        int len = n;
        s_new[0] = 1e9 + 10;
        s_new[1] = 1e9 + 11;
        int j = 2;
        for (int i = 0; i < len; i++) {
            s_new[j++] = s[i];
            s_new[j++] = 1e9 + 11;
        }
        s_new[j] = 1e9 + 12;//上面的三个数需要不相同
        return j;  // 返回 s_new 的长度
    }
    
    int manacher()
    {
        int len = init();  // 取得新字符串长度并完成向 s_new 的转换
        int max_len = -1;  // 最长回文长度
        int id;
        int mx = 0;
        for (int i = 1; i < len; i++)
        {
            if (i < mx) p[i] = min(p[2 * id - i], mx - i); 
            else p[i] = 1;
            while (s_new[i - p[i]] == s_new[i + p[i]])  
                p[i]++;
            if (mx < i + p[i]){
                id = i;
                mx = i + p[i];
            }
            max_len = max(max_len, p[i] - 1);
        }
        return max_len;
    }
    
    int main()
    {
        scanf("%d", &T);
        while (T--){
            scanf("%d", &n);
            for (int i = 0; i < n; i++) {
                scanf("%d", &s[i]);
            }
            printf("%d
    ", manacher());
        }
        return 0;
    }
  • 相关阅读:
    Ubuntu kylin 14.04 安装问题未解决
    C 语言实例
    C 语言实例
    C 语言实例
    C 语言实例
    C 语言实例
    C 语言实例
    C 语言实例
    C 语言实例
    C 语言实例
  • 原文地址:https://www.cnblogs.com/romaLzhih/p/9489815.html
Copyright © 2020-2023  润新知