Hihocoder 1032 最长回文子串

来源:互联网 发布:学知不足 教然后知困 编辑:程序博客网 时间:2024/05/22 14:43

题目链接:

http://hihocoder.com/problemset/problem/1032

题意:

求一个字符串中最大回文串的长度

思路:

回文串第一题,通过叙述思路来整理如何做好回文串题。

看到的博客上说有四种算法,分别是暴力枚举(n^3),动态规划(n^2),中心算法(n^2)manacher算法(n)

实现方式通过在相邻字符之间填充’#’的方法把字符串变为恒为奇数个字符的字符串,然后再开头插入’$’来防止溢出。dp[i]数组用于存储每个以i为中心的最大回文字符子串最右能到哪里,转换过来就是dp[i]-1是以i为中心的字符子串的最大长度。

下面开始叙述转移方程。设已经找到的最大字符子串的中心为id,它的右边界为mx。则有

dp[i] = gmin(dp[2*id-i],mx-i)。具体为:第一项dp[2*id-1]i关于id的对称点(因为从前向后遍历所以i关于id的对称点都在i的前面)。第二项为id为中心的最大字符子串(实际上也是目前找到的最大字符子串)的右边界到i的距离。dp[i]只更新到当前能更新的最大范围。到达顶端mx-i后,需要线性开始向后遍历(即增加dp[i]判断是否满足条件)。遍历结束更新idmx,同时进行i+1的判断。

准确说应该是一个2n的算法。

源码:

#include <cstdio>

#include <cmath>

#include <cstring>

#include <string>

#include <algorithm>

#include <iostream>

using namespace std;

#define gmin(a,b) a<b?a:b

#define gmax(a,b) a>b?a:b

const int MAXN = 1e6+5;

char str[MAXN],data[2*MAXN];

int dp[MAXN*2];

int main()

{

    int t;

    scanf("%d",&t);

    while(t--){

        scanf("%s",str);

        data[0] = '$';

        int len = strlen(str);

        for(int i=0; i<strlen(str); i++){

            data[i*2+1] = '#';

            data[i*2+2] = str[i];

        }

        data[len*2+1] = '#';

        data[len*2+2] = '\0';

        int id,mx;

        id = 0;

        mx = 1;

        int ans = 0;

        for(int i=0; i<2*len+1; i++)

            dp[i] = 1;

        for(int i=0; i<2*len+1; i++){

            int j = 2 * id - i;

            dp[i] = gmin(dp[j],mx-i);

            while(data[dp[i]+i] == data[i-dp[i]])

                dp[i]++;

            if(mx < dp[i]+i){

                mx = dp[i]+i;

                id = i;

            }

            ans = gmax(ans, dp[i]);

        }

//        printf("dp\n");

//        for(int i=0; i<2*len+1; i++)

//            printf("%d ",dp[i]);

        printf("%d\n",ans-1);

    }

    return 0;

}

 

0 0
原创粉丝点击