Given a string, your task is to count how many palindromic substrings in this string.
The substrings with different start indexes or end indexes are counted as different substrings even they consist of same characters.
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".
Note:
- The input string length won't exceed 1000.
Similar Questions: Longest Palindromic Substring Longest Palindromic Subsequence Palindromic Substrings
Next challenges:
方法一:O(n^2)的時間復雜度。
思路:回文字符串有奇數個字符時,當前i位置字母作為回文字符串的中心;有偶數個字符的時候當前i和i+1位置字母作為回文字符串的中心。
代碼:
1 public class Solution { 2 public int countSubstrings(String s) { 3 if(s == null) return 0; 4 int count = 0; 5 for(int i = 0; i < s.length(); i++) { 6 count += countPalindromicSubstrings(s, i, i); 7 count += countPalindromicSubstrings(s, i, i + 1); 8 } 9 return count; 10 } 11 12 public int countPalindromicSubstrings(String s, int begin, int end) { 13 int count = 0; 14 while(begin >= 0 && end < s.length() && s.charAt(begin) == s.charAt(end)) { 15 count++; 16 begin--; 17 end++; 18 } 19 return count; 20 } 21 }
方法二:O(n)的時間復雜度。
思路:先對字符串進行改造(例如原字符串是"bab",改造后是"#b#a#b#"),接着對改造后的字符串運行Manacher's Algorithm(“馬拉車”算法),得到以s[i]為中心的回文串的半徑RL[i](不包括中心。例如"a"的半徑就是0;"bab"以"a"為中心,半徑就是1),顯然,以s[i]為中心,RL[i]為半徑的回文串中含有的字回文串數目是(RL[i] + 1) / 2個。最后只要將每個(RL[i] + 1) / 2加和就是結果。
關於Manacher's Algorithm的學習資料:
https://segmentfault.com/a/1190000003914228
http://www.cnblogs.com/grandyang/p/4475985.html
代碼:
1 public class Solution { 2 public int countSubstrings(String s) { 3 String rs = "#"; 4 //改造 5 for(int i = 0; i < s.length(); i++) rs = rs + s.charAt(i) + "#"; 6 int[] RL = new int[rs.length()];//半徑 7 int pos = 0, maxRight = 0, count = 0; 8 for(int i = 0; i < rs.length(); i++) { 9 if(i < maxRight) { 10 RL[i] = Math.min(maxRight - i, RL[2 * pos - i]); 11 } 12 while(i - RL[i] - 1 >= 0 && i + RL[i] + 1< rs.length() && rs.charAt(i - RL[i] - 1) == rs.charAt(i + RL[i] + 1)) { 13 RL[i]++; 14 } 15 if(i + RL[i] > maxRight) { 16 pos = i; 17 maxRight = i + RL[i]; 18 } 19 count += (RL[i] + 1) / 2; 20 } 21 return count; 22 } 23 }