【问题标题】:Longest Palindromic Substring Problem - O(N^2 logN) Solution - Binary search [closed]最长回文子串问题 - O(N^2 logN) 解决方案 - 二分搜索 [关闭]
【发布时间】:2020-03-26 10:24:35
【问题描述】:

最长回文子串问题:
给定一个字符串 s,返回 s 中最长的回文子串。
例如。

Input: s = "babad"
Output: "bab"
Note: "aba" is also a valid answer.

问题
下面的代码是 Errichto(codeforces 的 RedCoder)的解决方案。这是对同一问题的 O(N^3) 解决方案的改进。在他的 youtube 频道上,他一步一步地逐步更有效地解决问题。但是我很难理解他对这个解决方案的方法。我的问题是:

  • good函数中L + x <= n条件有什么用
  • 在进行二分搜索之前,似乎已经完成了一些与奇偶校验相关的事情。为什么?它对解决方案的贡献是什么?
  • 这里的二分搜索有点奇怪。我了解基本的二进制搜索,但没有得到这个变体。谁能帮我解释一下?

代码

bool is_palindrome(string s) {
    string rev = s;
    reverse(rev.begin(), rev.end());
    return s == rev;
}
// returns true if there is a palindrome of length x
int good(int x, string s) {
    int n = s.length();
    for(int L = 0; L + x <= n; L++) {
        if(is_palindrome(s.substr(L, x))) {
            return L;
        }
    }
    return -1;
}
class Solution {
public:
    string longestPalindrome(string s) {
        int best_len = 0;
        string best_s = "";
        int n = s.length();
        for(int parity : {0, 1}) {
            int low = 1, high = n;
            if(low % 2 != parity) low++;
            if(high % 2 != parity) high--;
            while(low <= high) {
                int mid = (low + high) / 2;
                if(mid % 2 != parity) {
                    mid++;
                }
                if(mid > high) {
                    break;
                }
                int tmp = good(mid, s);
                if(tmp != -1) {
                    if(mid > best_len) {
                        best_len = mid;
                        best_s = s.substr(tmp, mid);
                    }
                    low = mid + 2;
                }
                else {
                    high = mid - 2;
                }
            }
        }
        return best_s;
    }
};

【问题讨论】:

  • 为什么要解释这个糟糕的代码?
  • 社区是为了帮助他人。我发现这段代码很复杂,需要帮助。
  • 您可以在互联网上找到任何不良代码,但这并不意味着社区应该花时间去挖掘不良代码。
  • 我努力解决这个问题..当我无法得到它时,我才寻求帮助。另外,我不会强迫任何人提供帮助。我会感谢任何给我答案的人。

标签: c++ c++11 binary-search longest-substring


【解决方案1】:
bool is_palindrome(string s) {
string rev = s;
reverse(rev.begin(), rev.end());
return s == rev;
}

这会复制字符串,反转该副本,然后将反转与原始字符串进行比较。不言自明但值得注意的是 c++ 具有反向迭代器,因此您可以执行 equal(rev.begin(), rev.end(), rev.rbegin()) ,它将从开始的每个元素与结束的每个元素进行比较,而无需复制。它也很聪明,一旦发现不匹配的字符就退出。

int good(int x, string s) {
int n = s.length();
for(int L = 0; L + x <= n; L++) {
    if(is_palindrome(s.substr(L, x))) {
        return L;
    }
}
return -1;
}

这是检查长度为 x 的任何可能的 s 子串是否是回文。 substr 获取起始字符的索引和从那里开始的字符数以获取其子字符串。例如,如果 s = "myString" 那么 substr(1, 3) 将给出 "ySt",从索引 1 开始的 3 个字符。如果起始位置加上字符数大于您离开的字符串的长度结束,这就是为什么它会在 L + x > n 时终止。

至于解决方案类... Ick。 想象一下,搜索空间是一个可能长度的数组:1, 2, 3, 4, 5, 6, 7 ...n,其中 n 是字符串的长度。对于它测试的每个长度,它将检查该长度的每个可能的子串,看一个是否是回文。如果有的话,它将检查可能长度数组的中点高于该测试长度,否则低于该长度。

二进制搜索的实际代码很难阅读和理解,如果你想理解它,你可以在 geekforgeeks 或 Rosetta 代码上找到更好的代码,以便你自己实现它。

理解逻辑的关键在于它与对不同可能长度的数组的二进制搜索相同。

【讨论】:

  • 你能解释一下上面代码中的奇偶校验逻辑吗?
【解决方案2】:

在下面的'good'函数中为什么for循环中的条件是L+x

因为正如您在评论中提到的那样:

// 如果存在长度为 x 的回文,则返回 true

我们关心的是子串 [L,L+x)。例如。第一次迭代:[0,x-1],第二次迭代:[1,(x-1)+1] 依此类推,直到 [n-x,n-1]。因此 L 一直到 n-x

【讨论】:

  • 你能解释一下上面代码中的奇偶校验逻辑吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-05
  • 2020-11-25
相关资源
最近更新 更多