回文字符串,指一个字符串,从左到右和从右到左是完全一样的。判断一个字符串是否是回文,最简单的方式字符串头尾字符一一比较:
1 bool IsPalindromes(const char *pstr, int n)
2 {
3 int i=0, j=n-1;
4 while(i<j && pstr[i++]==pstr[j--])
5 ;
6 if (i>=j) //i==j时,说明pstr长度为奇数,i>j时,说明长度为偶数
7 return true;
8
9 return false;
10 }
也可以用递归来处理,更加简洁:
1 bool IsPalindromes_R(const char *pstr, int n)
2 {
3 if(n==0 || n==1) //n==1说明pstr长度为奇数,n==0则长度为偶数
4 return true;
5 return pstr[0] == pstr[n-1] &&
6 IsPalindromes_R(pstr+1, n-2);
7 }
理解了回文的概念,那么来看看如何求出最长回文子串。最容易想到的就是暴力破解,求出每一个子串,之后判断是不是回文,找到最长的那个,这样的时间复杂度太高O(n^3)。换一种思路,回文子串都是以中间的某个字符作为中心,然后向两边伸展,这样处理时间复杂度为O(n^2)。代码如下:
1 void LongestPalindrome(const char *pstr, int n)
2 {
3 if(pstr == NULL || n<0)
4 return;
5
6 int i, j, k;
7 int maxlen = 0;
8 int start = 0;
9 for(i=0; i!=n; i++)
10 {
11 j=i-1, k=i+1; //这里表示如"aba"这样的相邻字符串
12 while(j>=0 && k<n && pstr[j]==pstr[k]) //回文为奇数情况
13 {
14 cout<<"odd:"<<pstr[j]<<" "<<pstr[k]<<endl;
15 if(k-j+1 > maxlen)
16 {
17 maxlen = k-j+1;
18 start = j;
19 }
20 j++;
21 k--;
22 }
23
24 j=i-1, k=i; //这里表示如"aa"这样的相邻字符串
25 while (j>=0 && k<n && pstr[j]==pstr[k]) //回文为偶数情况
26 {
27 cout<<"even:"<<pstr[j]<<" "<<pstr[k]<<endl;
28 if(k-j+1 > maxlen)
29 {
30 maxlen = k-j+1;
31 start = j;
32 }
33 j--;
34 k++;
35 }
36 }
37 cout<<"maxlen = "<<maxlen<<", start = "<<start<<endl;
38 char *pSubStr = new char[maxlen+1];
39 memset(pSubStr, 0x0, sizeof(char)*(maxlen+1));
40 strncpy_s(pSubStr, maxlen+1, pstr+start, maxlen);
41 cout<<"LongestPalindrome is: "<<pSubStr<<endl;
42 delete[] pSubStr;
43
44 return;
45 }