您的位置:首页 > 其它

Hihocoder 1032 最长回文子串

2015-06-20 11:53 225 查看
题目链接:
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]判断是否满足条件)。遍历结束更新id和mx,同时进行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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: