51Nod 1089 最长回文子串 V2 —— Manacher算法

题目链接:https://vjudge.net/problem/51Nod-1089


1089 最长回文子串 V2(Manacher算法)
基准时间限制:1 秒 空间限制:131072 KB 分值: 0  难度:基础题
回文串是指aba、abba、cccbccc、aaaa这种左右对称的字符串。
输入一个字符串Str,输出Str里最长回文子串的长度。
Input
输入Str(Str的长度 <= 100000)
Output
输出最长回文子串的长度L。
Input示例
daabaac
Output示例
5



题解:

普通的方法是枚举中心,然后向两边扩展。时间复杂度为O(n^2),而这里的数据量:len<=1e5,所以会超时。

Manacher算法:O(n)求出最长回文子串。(为什么是线性复杂度?自己也不太清楚,应该是mx为线性增长。)

(注:在首端加‘$’是防止在向左右扩散时在左端溢出(右端已经有‘\0’,故无需再设一个‘$’)。)



代码如下:

#include
#define rep(i,a,n) for(int (i) = a; (i)<=(n); (i)++)
#define ms(a,b) memset((a),(b),sizeof((a)))
using namespace std;
typedef long long LL;
const double eps = 1e-6;
const int INF = 2e9;
const LL LNF = 9e18;
const int mod = 1e9+7;
const int maxn = 1e5+10;

char s[maxn], Ma[maxn<<1];
int Mp[maxn<<1];

int Manacher(char *s, int len)
{
    int ret = 0;
    int ln = 0;
    Ma[0] = '$'; Ma[++ln] = '#';
    for(int i = 1; i<=len; i++)
    {
        Ma[++ln] = s[i];
        Ma[++ln] = '#';
    }
    Ma[ln+1] = 0;

    int mx = 1, id = 1;
    for(int i = 1; i<=ln; i++)
    {
        Mp[i] = mx>i?min(Mp[2*id-i], mx-i):1;
        while(Ma[i+Mp[i]]==Ma[i-Mp[i]]) Mp[i]++;
        if(i+Mp[i]>mx)
        {
            mx = i+Mp[i];
            id = i;
        }
        ret = max(ret,Mp[i]-1);
    }

    return ret;
}

int main()
{
    cin>>s+1;
    cout<< Manacher(s, strlen(s+1)) <


你可能感兴趣的:(字符串)