Example 1:
Input: "abc" Output: 3 Explanation: Three palindromic strings: "a", "b", "c".Example 2:
Input: "aaa" Output: 6 Explanation: Six palindromic strings: "a", "a", "a", "aa", "aa", "aaa".Palindromic Substrings:即对称的回文字符串
方法一: O(n ^ 2)
遍历字符串s,每次以"s[i]"和“s[i] s[j]”作为中心依次往外扩展,若对称,则总数加1。
以“abcde”为例,s[i]每次往外扩展得到的都是奇数字符串。如以a为中心,扩展集合是{a};以c为中心,扩展集合是{c, bcd,abcde}。
s[i] s[j]每次往外扩展得到偶数字符串,如以ab为中心,扩展集合是{ab};以b为中心{bc,abcd}。
因此以上述两种中心扩展方式可以不漏掉任何回文串。
class Solution {
public:
int result = 0;
void expandCenter(string s, int n, int start, int end){
while(start >= 0 && end < n && s[start--] == s[end++]){
result++;
}
}
int countSubstrings(string s) {
int n = s.size();
for(int i = 0;i < n;i++){
expandCenter(s, n, i, i); //筛选偶数字符串
expandCenter(s, n, i, i + 1); //筛选奇数字符串
}
return result;
}
};
方法二: O(n)
运用Manacher算法。下面来详细介绍一下。
首先将"abc"转换成"#a#b#c",目的是为了将单个字符作为回文字符串;center,right,p[]含义见注释;
如果p[j]<right - i,说明a[i]的半径没有超出right的边界而且等于a[j]的半径,此时p[i]=p[j]=p[2*center - i],其中i和j是关于center的对称点对,这个p[i]值是确定的;如果p[j] >= right - i,说明i的半径至少扩张到了right,right之后的部分要继续扩张。此时p[i]值不是确定的,但是我们让p[i]=right-i,因为半径为right-i是至少的,至于半径是否继续增加取决于right后面的部分,我们在扩张步骤计算。因此,p[i] = Math.min(right - i, p[2 * center - i])。
之后对a[i]进行半径扩展操作,并更新中心位置和最右位置。
最后result += (p[i] + 1) / 2,是因为之前拼接了“#”。
如#a#a#b#a#a#,b的半径#a#a#为5,共(5 + 1) / 2 = 3个回文字符串;
#a#a#,中间#的半径为a#为2,共一个回文串aa,(2 + 1) / 2 = 1;
class Solution {
public int countSubstrings(String s) {
String a = "#";
for(char c: s.toCharArray()){
a += c;
a += '#';
}
int length = a.length();
int[] p = new int[length]; //p[i]代表以a[i]为中心的最长回文字符串半径,初始化为0
int center = 0; //遍历过程中最长回文字符串的中心位置
int right = 0; //遍历过程中最长回文字符串的最右位置
int result = 0;
for(int i = 0;i < length;i++){
if(right > i){
p[i] = Math.min(right - i, p[2 * center - i]);
}
while(i + p[i] + 1 < length && i - p[i] - 1 >=0 && a.charAt(i + p[i] + 1) == a.charAt(i - p[i] - 1)){
p[i]++; //半径增加
}
if(i + p[i] > right){ //有了更长的回文字符串,更新中心位置和最右位置
right = i + p[i];
center = i;
}
result += (p[i] + 1) / 2;
}
return result;
}
}
本小白华中科技大学在读研究生,自然语言处理方向。现每日一更LeetCode Top 100 Liked Questions, 旨在于通过通俗易懂的画风和诸位计算机朋友们一起成长呀,不局限某题,争取举一反三,所有Questions均呈上C++和Java解法,不足之处多多指正,共同学习。