Leetcode 647. Palindromic Substrings


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:

  1. The input string length won't exceed 1000.

 

Similar Questions: Longest Palindromic Substring Longest Palindromic Subsequence Palindromic Substrings 

Next challenges: Longest Palindromic Subsequence

 

方法一: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 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM