题目5:
Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring.
/***************************************************************************************************
* (c) Copyright 1992-2015 Embedded Products Research Center
* All Rights Reserved
*
*\File main.c
*\Description 使用Manacher算法找出字符串S中唯一最长回文子串,时间复杂度为O(N)
*\Note
*\Log 2015.07.27 Ver 1.0
* 创建文件。
***************************************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/***************************************************************************************************
*\Function GetLen
*\Description 获取时间字符串长度
*\Parameter s
*\Return int
*\Note
*\Log 2015.07.27 Ver 1.0
* 创建函数。
***************************************************************************************************/
int GetLen(char* s)
{
int len = 0;
while (*(s++) != '\0')
{
len++;
}
return len;
}
/***************************************************************************************************
*\Function StringExten
*\Description 扩充字符串到extern_s,例"abc"扩充为"#a#b#c#"
*\Parameter s
*\Parameter extern_s
*\Return int
*\Note
*\Log 2015.07.27 Ver 1.0 凌琨
* 创建函数。
***************************************************************************************************/
void StringExten(char* s, char* extern_s)
{
int len = 0;
int i = 0;
len = GetLen(s);
for (i = 0; i < len; i++)
{
extern_s[2*i] = '#';
extern_s[2*i+1] = s[i];
}
extern_s[2*i] = '#';
extern_s[2*i+1] = '\0';
}
/***************************************************************************************************
*\Function StringCut
*\Description 去除扩充字符
*\Parameter s
*\Parameter res
*\Return void
*\Note
*\Log 2015.07.27 Ver 1.0
* 创建函数。
***************************************************************************************************/
void StringCut(char* s, char* res)
{
int len = 0;
int i = 0;
len = GetLen(s);
for (i = 0; i < (len-1)/2; i++)
{
res[i] = s[2*i+1];
}
res[i] = '\0';
}
char* longestPalindrome(char* s)
{
int i = 0;
int temp_l = 0;
int temp_r = 0;
int s_len = 0;
int extern_len = 0;
char* extern_s = NULL; /* 扩充后字符串 */
char* res = NULL; /* 存放最终结果 */
int* arr_r = NULL; /* 记录每个位置为中心的回文半径 */
int max_ptr = 0; /* 最长回文可到的标号 */
int max_center = 0; /* 最长回文的中心 */
s_len = GetLen(s);
extern_s = (char*)malloc(2*s_len+2);
res = (char*)malloc(s_len+1); /* 存放返回结果 */
arr_r = (int*)malloc(sizeof(int)*(2*s_len+2)); /* 每个节点的回文半径长度 */
StringExten(s, extern_s);
extern_len = GetLen(extern_s);
/* 遍历求得所有的arr_r[i] */
for (i = 0; i < extern_len; i++)
{
arr_r[i] = 0;
/* 节点不被之前最大回文所包括在内,按普通方法求该点的回文半径 */
if (i >= max_ptr)
{
temp_l = i;
temp_r = i;
arr_r[i] = 1;
while (--temp_l >= 0 && ++temp_r <= extern_len)
{
if (extern_s[temp_l] == extern_s[temp_r])
{
arr_r[i] += 1;
}
else
{
break;
}
}
}
else /* 被之前求得的最大回文半径所包括在内,分了三种情况 */
{
if ((2*max_center-i - arr_r[2*max_center-i] + 1) < 2*max_center-max_ptr)
{
arr_r[i] = arr_r[2*max_center - i];
}
if ((2*max_center-i - arr_r[2*max_center-i] + 1) > 2*max_center-max_ptr)
{
arr_r[i] = arr_r[max_center] - (i - max_center);
}
if ((2*max_center-i - arr_r[2*max_center-i] + 1) == 2*max_center-max_ptr)
{
arr_r[i] = arr_r[2*max_center - i];
temp_l = i - (max_ptr - i);
temp_r = max_ptr;
while (--temp_l >= 0 && ++temp_r <= extern_len)
{
if (extern_s[temp_l] == extern_s[temp_r])
{
arr_r[i]++;
}
else
{
break;
}
}
}
}
/* 判断是否修改标记 */
if (arr_r[i] > arr_r[max_center])
{
max_center = i;
max_ptr = max_center + arr_r[i] - 1;
}
}
extern_s[max_ptr+1] = '\0';
StringCut(&extern_s[max_center+1-arr_r[max_center]], res);
free(extern_s);
free(arr_r);
return res;
}
void main()
{
static char str[] = "ccc";
char* res = (char*)malloc(10000);
res = longestPalindrome(str);
printf("%s\n", res);
getchar();
}