[模板] manacher

manacher是一种处理字符串的算法,用来判断最长的回文串的长度.

主要思路就是要让指针跳跃就行了,mid和maxright,分别代表对称轴和最左边的位置.再搞一个存最长串的东西,来回更新答案.

(其实就是乱搞暴力)

题干:

题目描述

给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度.

字符串长度为n
输入输出格式
输入格式:
一行小写英文字符a,b,c...y,z组成的字符串S
输出格式:
一个整数表示答案
输入输出样例
输入样例#1: 复制
aaa
输出样例#1: 复制
3
说明
字符串长度len <= 11000000

代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
#define duke(i,a,n) for(int i = a;i <= n;i++)
#define lv(i,a,n) for(int i = a;i >= n;i--)
#define clean(a) memset(a,0,sizeof(a))
const int INF = 1 << 30;
typedef long long ll;
typedef double db;
template <class T>
void read(T &x)
{
    char c;
    bool op = 0;
    while(c = getchar(), c < '0' || c > '9')
        if(c == '-') op = 1;
    x = c - '0';
    while(c = getchar(), c >= '0' && c <= '9')
        x = x * 10 + c - '0';
    if(op) x = -x;
}
template <class T>
void write(T x)
{
    if(x < 0) putchar('-'), x = -x;
    if(x >= 10) write(x / 10);
    putchar('0' + x % 10);
}
#define maxn 50000500
int n,hw[maxn],ans = 1;
char a[maxn],s[maxn << 1];
void manacher()
{
    int maxright = 0,mid;
    duke(i,1,n - 1)
    {
        if(i < maxright)
            hw[i] = min(hw[(mid << 1) - i],hw[mid] + mid - i);
        else
            hw[i] = 1;
        for(;s[i +hw[i]] == s[i - hw[i]];++hw[i]);
        if(hw[i] + i > maxright)
        {
            maxright = hw[i] + i;
            mid = i;
        }
    }
}
void change()
{
    s[0] = s[1] = '#';
    duke(i,0,n - 1)
    {
        s[i * 2 + 2] = a[i];
        s[i * 2 + 3] = '#';
    }
    n = n * 2 + 2;
    s[n] = 0;
}
int main()
{
    scanf("%s",a);
    n = strlen(a);
    change();
    manacher();
    ans = 1;
    duke(i,0,n - 1)
    ans = max(ans,hw[i]);
    printf("%d\n",ans - 1);
    return 0;
}

 

posted @ 2018-09-22 13:59  DukeLv  阅读(125)  评论(0)    收藏  举报