今天继续刷LeetCode,第5题,找到一个字符串中最长的子字符串。
分析:
方法一:两层遍历找到所有的子字符串,然后同时判断这些子字符串是否是回文,并求出最大长度。
方法二:马拉车算法,可以在O(n)的时间内完成查找最长子字符串。
问题:
1、是否需要考虑回文数是单数还是双数?
2、马拉车算法。
附上C++代码1:
class Solution {
public:
string longestPalindrome(string s) {
if (s.size() < 2) return s;
int n = s.size(), maxLen = 0, start = 0;
for (int i = 0; i < n - 1; ++i) {
searchPalindrome(s, i, i, start, maxLen);
searchPalindrome(s, i, i + 1, start, maxLen);
}
return s.substr(start, maxLen);
}
void searchPalindrome(string s, int left, int right, int& start, int& maxLen) {
while (left >= 0 && right < s.size() && s[left] == s[right]) {
--left; ++right;
}
if (maxLen < right - left - 1) {
start = left + 1;
maxLen = right - left - 1;
}
}
};
附上discuss里面的马拉车算法代码:
class Solution {
public:
string longestPalindrome(string s) {
string t ="$#";
for (int i = 0; i < s.size(); ++i) {
t += s[i];
t += '#';
}
int p[t.size()] = {0}, id = 0, mx = 0, resId = 0, resMx = 0;
for (int i = 1; i < t.size(); ++i) {
p[i] = mx > i ? min(p[2 * id - i], mx - i) : 1;
while (t[i + p[i]] == t[i - p[i]]) ++p[i];
if (mx < i + p[i]) {
mx = i + p[i];
id = i;
}
if (resMx < p[i]) {
resMx = p[i];
resId = i;
}
}
return s.substr((resId - resMx) / 2, resMx - 1);
}
};
附上Python代码:
class Solution:
def longestPalindrome(self, s: str) -> str:
start = end = 0
for i in range(len(s)):
len1 = self.centerexpand(s, i, i) #回文串长度为奇数,aba
len2 = self.centerexpand(s, i, i+1) #回文串长度为偶数,abba
maxlen = max(len1, len2)
if maxlen > end - start + 1:
start = i - (maxlen - 1)//2
end = i + maxlen//2
return s[start: end+1]
def centerexpand(self,s,l,r):
while l >= 0 and r < len(s) and s[l] == s[r]:
l -= 1
r += 1
return r - l - 1
不知道哪里出问题的代码:
class Solution {
public:
string longestPalindrome(string s) {
int n=s.length();
int low=0,len=0;
for(int i=0;i<n;i++)
{
for(int j=i;j<n;j++)
{
if(isPalindromic(s,i,j)&&(j-i+1)>len)
{
len=j-i+1;
low=i;
}
}
}
return s.substr(low,low+len);
}
bool isPalindromic(string s,int i,int j)
{
while(i<j)
{
if(s[i]!=s[j])
return false;
i++;
j--;
}
return true;
}
};