一个字符串求其最长的子回文串
爆破
分割子字符串,从1到2,1到3,1到4一直到完成。之后从2到3,3到4一直到完成。
检测每一个字符串是否合法。
其中if(int j = i - j + 1) 是一个剪枝操作,从而提升部分效率,为什么要加1呢,因为算的是这个串的长度。
class Solution {
public:
bool isPalinDrome(string& s, int letf, int right){
while(letf < right){
if(s[letf] != s[right]){
return false;
}
letf++;
right--;
}
return true;
}
string longestPalindrome(string s) {
if(s.size() <= 1){
return s;
}
int begin = 0;
int len = 1;
//分割字串,从第一个开始,1到2,1到3
//2到4 一直到完
for(int i = 0; i < s.size() - 1; i++){
for(int j = i + 1; j < s.size(); j++){
if((j - i + 1) > len && isPalinDrome(s, i, j)){
len = j - i + 1;
begin = i;
}
}
}
s = s.substr(begin, len);
return s;
}
};
中心扩散
什么意思呢,以某一个元素为中心,两边扩散进行寻找回文串。然后将中间的结果进行储存。
细节: 在用比对函数的时候返回长的时候,事实上在while出循环的时候此时字符串已经不满足,所以需要-2;
begin = i - (len-1)/2;例如字符串 abbabde 和 abbaabda,找规律即可看出,由于此时i=3,回文串长len = 3;所以起点为 3 - 3/2 = 2;而另一个i = 4,起点为 (4 - 1)%2 = 2; 由于奇数的回文串减掉一个字符并不会导致错误。所以说归纳一下 i - (len -1) / 2;
class Solution {
public:
int isPalinDrome(string& s, int letf, int right){
int ret;
int i = letf , j = right;
while(i >= 0 && j < s.size()){
if(s[i] != s[j]){
break;
}
i--;
j++;
}
return j - i + 1 -2; //原因是,循环跳出的时候已经不满足了
}
string longestPalindrome(string s) {
if(s.size() <= 1){
return s;
}
int begin = 0;
int len = 1;
//从零号开始, 防止没有
for(int i = 0; i < s.size() - 1; i++){
int odd = isPalinDrome(s, i, i);
int even = isPalinDrome(s, i, i + 1);
odd = max(odd, even);
if(odd > len){
begin = i -(odd - 1) /2;
len = odd;
}
}
s = s.substr(begin, len);
return s;
}
};
动态规划
如果是回文串那么第一个和最后一个相等,倒数第二个和整数第二个相等,所以 dp[i][j] = (s[i] == s[j]) && dp[i+1][j-1] ([i+1][j-1] 是一个子区间), 由子区间肯定是长度大于2的,j -1 - (i + 1) + 1< 2 的时候那么这个点的值肯定为true
class Solution {
public:
string longestPalindrome(string s) {
if(s.size() <= 1){
return s;
}
int begin = 0;
int len = 1;
bool dp[s.size()][s.size()];
int i;
for(int i = 0; i < s.size(); i++){
dp[i][i] = true;
}
for(int j = 1; j < s.size(); j++){
for(int i = 0; i < j ;i++){
if(s[i] != s[j]){
dp[i][j] = false;
}
else{
if(j - i + 1 < 4){
dp[i][j] = true;
}
else{
dp[i][j] = dp[i + 1][j -1];
}
}
if(dp[i][j] == true && j - i >= len){
begin = i;
len = j - i + 1;
}
}
}
s = s.substr(begin, len);
return s;
}
};
后面还有一个马拉车算法时间不是特别充裕,后面再补上