问题描述:给定一个字符串,寻找最长回文子串。
猜想:当拿到这个问题,最初的想法打算用分治法来解,也许是受到近期在看算法导论的影响,其实它跟算法导论里"最大子数组"问题类似。但是,唯一的不足:没有被accepted,但是在vs2010里我解决了这个问题。针对这个问题,我花费2天的时间去完善,但是仍然存在瑕疵,故想记录下来当时的想法,也希望得到你们的帮助。
1、算法描述:
step1: 先考虑特殊情况,或者说是最小子问题。
若字符串只有一个字符即len=1;
若字符串len=2,则只需考虑两者是否相等;
若字符串len=3进行处理;
(任何的问题的解,都可以分解成以上子问题解的组合)
step2: 将问题划分成3种情况考虑,即左:left_result、右:right_result、跨界:cross_result。然后依次递归调用函数Search_Palindrome寻找回文子串。最后比较left_result、right_result、cross_result三者的回文子串长度,选择最长的结果返回。
2、具体实现参考以下代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct result_palindrome
{
char *_low;
char *_high;
int _sum;
}Result;
char *s_buf;
//declaration
Result *Cross_search_palindrome(char *s_start, char *s_mid, char *s_end, int len);
bool Compare_literal(char *s_start, char *s_end, char *str, int len);
Result *Search_Palindrome(char *s_start, char *s_end, int len);
char* longestPalindrome(char* s);
bool Compare_literal(char *s_start, char *s_end, char *str, int len)
{
int i,j;
for (i=1,j=len; i<=j; i++,j--)
{
if (*s_start!=*str || *s_end!=*str)
{
return false;
}
s_start++;
s_end--;
}
return true;
}
Result *Cross_search_palindrome(char *s_start, char *s_mid, char *s_end, int len)
{
Result *result=NULL;
int length=0;
bool Com_result;
char *max_left;
char *max_right;
char *_left, *_right;
_left=s_mid-1;
_right=s_mid+1;
result=(Result*)malloc(sizeof(Result)*1);
if (result==NULL)
{
printf("error in memory in function Cross_search_palindrome\n");
}
for (; _left!=s_start && _right!=s_end; _left--,_right++)
{
if (*_left!=*_right)
{
/*length=_right-_left+1-2;*/
result->_sum=2*length+1;//come error
result->_low=_left+1;
result->_high=_right-1;
return result;
}
length++;
}
if (_left!=s_start /*&& _right==s_end*/)
{
if (*_left!=*_right)
{
length=length;
result->_sum=2*length+1;//come error
result->_low=_left+1;
result->_high=_right-1;
return result;//forget return
}
length++;
_left--;
Com_result=Compare_literal(_left+1,_right,_left,2*length+1);
if (Com_result==false)
{
result->_sum=2*length+1;//come error
result->_low=_left+1;
result->_high=_right;
return result;
}
//all element is the same
/*length=length+1;*/
result->_sum=2*length+2;//come error
result->_low=_left;
result->_high=_right;
return result;
}
else
{
if (*_left!=*_right)
{
result->_sum=2*length+1;
result->_low=_left+1;
result->_high=_right-1;
return result;
}
length++;
result->_sum=2*length+1;
result->_low=_left;
result->_high=_right;
return result;
}
}
Result *Search_Palindrome(char *s_start, char *s_end, int len)
{
if (len==2)
{
Result *result2=(Result*)malloc(sizeof(Result)*1);
if (*s_start==*s_end)
{
result2->_low=s_start;
result2->_high=s_end;
result2->_sum=2;
return result2;
}
else
{
result2->_low=NULL;
result2->_high=NULL;
result2->_sum=0;
return result2;
}
}
if (len==3)
{
Result *result3=(Result*)malloc(sizeof(Result)*1);
if (*s_start==*s_end)
{
result3->_sum=3;
result3->_low=s_start;
result3->_high=s_end;
return result3;
}
else if (*s_start==*(s_start+1))
{
result3->_sum=2;
result3->_low=s_start;
result3->_high=(s_start+1);
return result3;
}
else if (*(s_start+1)==*s_end)
{
result3->_sum=2;
result3->_low=(s_start+1);
result3->_high=s_end;
return result3;
}
}
if (s_start==s_end)
{
Result *result4=(Result*)malloc(sizeof(Result)*1);
result4->_low=s_start;
result4->_high=s_end;
result4->_sum=1;
return result4;
}
else
{
Result *left_result=(Result*)malloc(sizeof(Result)*1);
Result *right_result=(Result*)malloc(sizeof(Result)*1);
Result *cross_result=(Result*)malloc(sizeof(Result)*1);
left_result=Search_Palindrome(s_start,s_start+len/2,len/2+1);
right_result=Search_Palindrome(s_start+len/2+1,s_end,len/2-1);
cross_result=Cross_search_palindrome(s_start,s_start+len/2,s_end,len);
if (left_result->_sum>=right_result->_sum && left_result->_sum>=cross_result->_sum)
{
return left_result;
}
else if (right_result->_sum>=left_result->_sum && right_result->_sum>=cross_result->_sum)
{
return right_result;
}
else if (cross_result->_sum>=left_result->_sum && cross_result->_sum>=right_result->_sum)
{
return cross_result;
}
}
}
char* longestPalindrome(char* s) {
//count the length of s
int length=0;
int Palindrome_length=0;
char *low, *high;
char *c_s=s;
char *result_palindrome=NULL;
char *buf;
while(*c_s!='\0')
{
length++;
c_s++;
}
printf("string length is %d\n",length);
low=s;
high=s+length-1;
Result *back_value=Search_Palindrome(low,high,length);
if (back_value==NULL)
{
printf("something wrong in function Search_Palindrome\n");
exit(-1);
}
Palindrome_length=back_value->_sum;
printf("Palindrome string length is %d\n",Palindrome_length);
//open a new memory
result_palindrome=(char*)malloc(sizeof(char)*length);
if (result_palindrome==NULL)
{
printf("error in open memory\n");
exit(-1);
}
buf=result_palindrome;
low=back_value->_low;
high=back_value->_high;
while(low!=high)
{
*result_palindrome=*low;
low++;
result_palindrome++;
}
*result_palindrome=*low;
*(result_palindrome+1)='\0';
result_palindrome=buf;
return result_palindrome;
}
主函数:
void main()
{
char str[]="cfcaeff";//"cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc";//"zeusnilemacaronimaisanitratetartinasiaminoracamelinsuez"
char *back_str=longestPalindrome(str);
if (back_str==NULL)
{
printf("something wrong in function longestPalindrome\n");
exit(-1);
}
printf("longestPalindrome is %s\n",back_str);
/* free(back_str);*/
return;
}
3、结果
当给定字符串"cfcaeff",最长回文子串为"cfc",实验结果如下。
最后给出unaccepted的原因:
但是,当给定长度为1000的字符串"cccc....cccc"时,vs2010结果是正确的,如下所示。
对于其他可以自行验证。针对未接受的原因或者程序中的缺点,希望大家给出宝贵的意见,谢谢!