在上一篇的文章中说到了,最长回文子串的问题,并且提到了基本的解决办法,即暴力求解法。效率O(N^3)
中心法求最长回文子串
我们知道回文字符串是以字符串中心对称的,如abba以及aba等。一个更好的办法是从中间开始判断,因为回文字符串以字符串中心对称。一个长度为N的字符串可能的对称中心有2N-1个,至于这里为什么是2N-1而不是N个,是因为可能对称的点可能是两个字符之间,比如abba的对称点就是第一个字母b和第二个字母b的中间。因此可以依次对2N-1个中心点进行判断,求出最长的回文字符串即可。
所以,要考虑回文是奇数还是偶数的情况。

#include<stdio.h> #include<stdlib.h> #include<ctype.h> #define MAXN 500+10 char buf[MAXN],s[MAXN]; int index[MAXN]; int main() { int i,j; int start = 0,end = 0; int max = 1; int m = 0,n; fgets(buf,sizeof(s),stdin); n = strlen(buf); //剔除其中的非字母字符,并且全部转换为大写字母 for(i = 0;i<n;i++) { if(isalpha(buf[i])) { index[m] = i; s[m++] = toupper(buf[i]); } } for(i = 0;i<m;i++) { /**奇数情况下*/ /**以i为中心,向左向右移动j,判断是否相同*/ /**这样求出的长度就是2*j+i*/ for(j = 0;i+j<m && i-j>=0;j++) { if(s[i-j] != s[j+i]) break; if(2*j+1 > max) { max = 2*j+1; start = i-j; end = i+j; } } /**偶数情况下*/ /**以i 和 i+1为中心,左右移动j,再判断*/ for(j = 0;i-j>=0 && i+1+j<m;j++) { if(s[i-j] != s[i+1+j]) break; if(2*j+2 > max) { max = 2*j+2; start = i-j; end = i+j+1; } } } printf("max = %d ",max); for(i = index[start];i<=index[end];i++) printf("%c",buf[i]); putchar(10); return 0; }