题目:Longest Palindromic Substring
查找最长回文子串
思路:
一个指针从头部,一个指针从尾部,对比每一个字母,若相等则可能是回文子串,则,检测子串是否回文,是则比较和已知的子串长度,更长就记录其起始和终止坐标,否则就放弃。
1 /********************************************************************** 2 Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000. 3 Example: 4 Input: "babad" 5 Output: "bab" 6 Note: "aba" is also a valid answer. 7 Example: 8 Input: "cbbd" 9 Output: "bb" 10 **********************************************************************/ 11 #include <stdio.h> 12 #include <ctype.h> 13 14 char* longestPalindrome(char* s) { 15 int length = strlen(s); 16 int i,j,max = 1,maxi = 0,maxj = 0,flag = 1;//flag标志是否是回文子串 17 for(i = 0;i < length && i + max < length;i++){//从头开始检测,最后剩余未检测长度少于一直最长解则放弃 18 for(j = length - 1;j > i;j--){//从尾部开始检测 19 flag = 1; 20 if(s[i] == s[j]){//可能回文 21 int head = i + 1,tail = j - 1; 22 while(head < tail){//检测是否是回文子串 23 if(s[head] != s[tail]){ 24 flag = 0; 25 break; 26 } 27 head++; 28 tail--; 29 } 30 if(flag == 1){//如果是回文子串 31 if(max < j - i + 1){//长度是否比已知最优解长 32 max = j - i + 1; 33 maxi = i; 34 maxj = j; 35 } 36 break;//继续收缩尾部指针,也得不到更优的解,所以放弃 37 } 38 } 39 } 40 } 41 42 char *substr = (char *)malloc((max + 1)*sizeof(char)); 43 memset(substr,0,(max + 1)*sizeof(char)); 44 strncpy(substr,s + maxi,max); 45 return substr; 46 } 47 48 void main(){ 49 char s[] = "babadada"; 50 char *sp = longestPalindrome(s); 51 printf("%s\n",sp); 52 free(sp); 53 }
上面的思路是从两边向中间收束,另一个思路是从中间向两边发散。
具体如下:
先找当前下标为中心的回文子串,比较它和最优解,更优则更新最优解,
递归查找中心点向左和向右偏移后的回文子串。
1 /********************************************************************** 2 Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000. 3 Example: 4 Input: "babad" 5 Output: "bab" 6 Note: "aba" is also a valid answer. 7 Example: 8 Input: "cbbd" 9 Output: "bb" 10 **********************************************************************/ 11 #include <stdio.h> 12 #include <ctype.h> 13 14 int max = 1;//记录已知最长的回文子串的长度 15 int maxi = 0;//记录已知最长的回文子串的头部坐标 16 int maxj = 0;//记录已知最长的回文子串的尾部坐标 17 18 void longestPSubstring(char *s,int i){//记录当前搜索的位置 19 int head = i - 1; 20 int tail = i + 1; 21 int length = strlen(s); 22 while((head >= 0 || tail < length) && s[head] == s[tail]){//检测以i为中心的回文子串 23 head--; 24 tail++; 25 } 26 if(tail - head - 1 > max){//比较以i为中心的回文子串是否更长 27 maxi = head + 1; 28 maxj = tail - 1; 29 max = tail - head - 1; 30 } 31 32 if(i - 1 > 0){ 33 longestPSubstring(s,i - 1);//向左偏移 34 } 35 if(i + 1 < length - 1){ 36 longestPSubstring(s,i + 1);//向右偏移 37 } 38 } 39 40 char* longestPalindrome(char* s) { 41 int length = strlen(s); 42 longestPSubstring(s,length/2); 43 44 char *substr = (char *)malloc((max + 1)*sizeof(char)); 45 memset(substr,0,(max + 1)*sizeof(char)); 46 strncpy(substr,s + maxi,max); 47 return substr; 48 } 49 50 void main(){ 51 char s[] = "babadada"; 52 char *sp = longestPalindrome(s); 53 printf("%s\n",sp); 54 free(sp); 55 }