给你一个字符串 s,找到 s 中最长的回文子串。
输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。
输入:s = "cbbd"
输出:"bb"
public class Solution {
public string LongestPalindrome(string s)
{
string result = "";
int n = s.Length;
for (int i = 0; i < n; i++)
{
for (int j = i; j < n; j++)
{
// 检查 s[i]到s[j]是否是回文串,如果是,且长度大于result长度,就更新它
int p = i, q = j;
bool isPalindromic = true;
while (p < q)
{
if (s[p++] != s[q--])
{
isPalindromic = false;
break;
}
}
if (isPalindromic)
{
int len = j - i + 1;
if (len > result.Length)
{
result = s.Substring(i, len);
}
}
}
}
return result;
}
}
P[i,j] = p(i+1,j-1) && ( s[i]==s[j] )
若子串长度为1,即 j==i, 则 P[i,j] = P[i,i] = true;
若子串长为2,即j==i+1, 则 P[i,j] = P[i,i+1] = ( s[i]==s[i+1] )
public class Solution {
public string LongestPalindrome(string s)
{
int n = s.Length;
bool[,] P = new bool[n, n];
string result = "";
//遍历所有的长度
for (int len = 1; len <= n; len++)
{
for (int start = 0; start < n; start++)
{
int end = start + len - 1;
if (end >= n) //下标已经越界,结束本次循环
break;
//长度为 1 和 2 的单独判断下
P[start, end] = (len == 1 || len == 2 || P[start + 1, end - 1]) && s[start] == s[end];
if (P[start, end] && len > result.Length)
{
result = s.Substring(start, len);
}
}
}
return result;
}
}
- i==2指向c,我们初始化两个指针p与q都指向这个c
- p–,q++,p指向了左边b,q指向了右边b
- 因为s[p]==s[q], 所以再次执行p–,q++,此时p指向了最左边a,q指向了最右边c
- 因为s[p]!=s[q],所以结束扩展。
public class Solution {
public string LongestPalindrome(string s)
{
string result = "";
int n = s.Length;
int end = 2 * n - 1;
for (int i = 0; i < end; i ++)
{
double mid = i / 2.0;
int p = (int)(Math.Floor(mid));
int q = (int)(Math.Ceiling(mid));
while (p >= 0 && q < n)
{
if (s[p] != s[q]) break;
p--; q++;
}
int len = q - p - 1;
if (len > result.Length)
result = s.Substring(p + 1, len);
}
return result;
}
}
public class Solution {
public string PreProcess(string s)
{
string t = "^";
int n = s.Length;
if (n == 0) return "^$";
for (int i = 0; i < n; i++)
{
t += "#" + s[i];
}
t += "#$";
return t;
}
// 方法四:马拉车算法 108ms,26.4M
public string LongestPalindrome(string s)
{
string t = PreProcess(s);
int n = t.Length;
int[] p = new int[n];
int c = 0, r = 0;
//计算P
for (int i = 1; i < n - 1; i++)
{
int j = 2 * c - i;
//情况2和3可以总结为 p[i]= min(r - i + 1, p[j]) ,情况1为 p[i]=1;
p[i] = r > i ? Math.Min(r - i + 1, p[j]) : 1;
//对于情况4和1,直接扩展即可;
//对于情况2和3,也可以直接扩展;虽然一定扩展不了,但是这样的计算过程比“判断是情况2或3”的计算量还要小,仔细品味
while (t[i - p[i]] == t[i + p[i]])
{
p[i]++;
}
if (i + p[i] > r)
{
//找到了更长的回文串,更新c和r
c = i;
r = i + p[i] - 1;
}
}
// 找出 P 的最大值
int maxLen = 0;
int centerIndex = 0;
for (int i = 1; i < n - 1; i++)
{
int len = p[i] - 1;
if (len > maxLen)
{
maxLen = len;
centerIndex = i;
}
}
int start = (centerIndex - maxLen) / 2;
return s.Substring(start, maxLen);
}
}