manacher算法
通过增大空间复杂度来减少找字串的时间,使之降为o(n)
具体方法可见
(漫画)如何找到字符串中的最长回文子串?
小明的字符串问题
描述
小明刚刚做完了回文电话号码的问题,觉得意犹未尽,开始思考一个升级版的问题:随便给一个长度不超过1000的字符串s,一定可以找到很多回文子串,例如s=“babad”,可以找到"bab"和"aba",那么在这些回文子串中,最长的那个子串是什么呢?请你写一个程序帮小明回答这个问题。
如果有多个相同长度的回文子串,请输出最先出现的那个。
输入
一个长度不超过1000的字符串,字符串保证不含空格。
输出
最早出现的、最长的那个回文子串
输入样例 1
cbbd
输出样例 1
bb
此为题解,c语言方案
#include <stdio.h>
#include <string.h>
#define min(a,b) a>b? b:a
void find_palindrome(char *s, char *r)
{
char t[2500]={0},len[2500]={0};//len[]->长度;t->用于处理的string
t[0]='*';t[1]='#';
for(int i=0;s[i]!=0;i++)//预处理 +‘#’
{
t[2*i+2]=s[i];
t[2*i+3]='#' ;
}
int mx=0,i,mid=0,ans=0,x;
for( i=1;t[i]!=0;i++)
{
if(i<mx)
len[i]= min(len[mid*2-i],mx-i);
else len[i]=1;
while(t[i-len[i]]==t[i+len[i]])
len[i]++;
if(len[i]+i>mx)
{
mx=len[i]+i;
mid=i;
}
/*!!注意mid不是最大的中间位置!!!
是当前的可容纳最多元素的字串的中间位置
mx边界 need choose the big */
if(len[i]>ans)
{
ans=len[i];
x=i;//x——>最大子串的位置
}
} //ans->the length of the longest string
// you can try a example like abba->*a#b#b#a#
//or aba->#a#b#a#
ans--;//-1就将半径变为长度
int j=0;
for(i=x-ans;i<=x+ans;i++)//mid -〉 t[]中的位置
{
if(t[i]!='#'&&t[i]!='*')
{
r[j]=t[i];
j++;
}
}
}//题目要求输出最长字串
int main()
{
char s[1001]= {0}, r[1001] = {0};
scanf("%s", s);
find_palindrome(s, r);
printf("%s", r);
return 0;
}