回文串问题
1.回文串的判断
#include <iostream> #include <string.h> using namespace std; //回文串的判断 bool isPalindrome(const char* src) { if(src == NULL) return true; int end = strlen(src)-1,begin = 0; while(begin < end)//从两边向中间判断,当然也可以从中间向两边判断 { if(src[begin] != src[end]) return false; begin ++; end --; } return true; } int main() { string s1; cin>>s1; cout<<isPalindrome(s1.c_str()); return 0; }
2.最长回文子串
中心扩展就是把给定的字符串的每一个字母当做中心,向两边扩展,这样来找最长的子回文串。算法复杂度为O(N^2)。
但是要考虑两种情况:
1、像aba,这样长度为奇数。
2、像abba,这样长度为偶数。
int expandAroundCenter(const char* src,int left,int right)//从中间往两头判断最长回文串 { int length = strlen(src); while(left >= 0 && right < length && src[left] == src[right]) { left --; right ++; } return right - left - 1; } void LongestPalindromeCenter(const char* src) { if(src == NULL) return; int length = strlen(src); int i,maxLen = 1,begin = 0,end = 0; for(i = 0;i < length;i++) { int len = expandAroundCenter(src,i,i);//针对奇数 if(len > maxLen) { maxLen = len; begin = i - ((len-1) >> 1); end = i + ((len-1) >> 1); } len = expandAroundCenter(src,i,i+1);//针对偶数 if(len > maxLen) { maxLen = len; begin = i - (len >> 1) + 1; end = i + (len >> 1); } } for(i = begin;i <= end;i++) cout<< src[i]; cout << endl; } int main() { string s1; cin>>s1; //cout<<isPalindrome(s1.c_str()); LongestPalindromeCenter(s1.c_str()); return 0; }
动态规划法:
回文字符串的子串也是回文,比如P[i,j](表示以i开始以j结束的子串)是回文字符串,那么P[i+1,j-1]也是回文字符串。这样最长回文子串就能分解成一系列子问题了。这样需要额外的空间O(N^2),算法复杂度也是O(N^2)。
首先定义状态方程和转移方程:
P[i,j]=0表示子串[i,j]不是回文串。P[i,j]=1表示子串[i,j]是回文串。
P[i,j]{=P[i+1,j-1] , if(s[i]==s[j])
=0 , if(s[i]!=s[j])