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".


Step 1: Start a for loop to point at every single character from where we will trace the palindrome string.
checkPalindrome(s,i,i); //To check the palindrome of odd length palindromic sub-string
checkPalindrome(s,i,i+1); //To check the palindrome of even length palindromic sub-string

Step 2: From each character of the string, we will keep checking if the sub-string is a palindrome and increment the palindrome count. To check the palindrome, keep checking the left and right of the character if it is same or not.

First Loop:
0_1500788783696_300147d3-e98e-4977-83f1-9eb8213a485e-image.png
Palindrome: a (Count=1)
0_1500788808121_fec1dec5-ab5f-44cf-8dbd-eb2780e8d65f-image.png
Palindrome: aa (Count=2)

Second Loop:
0_1500788845582_881440b8-6dde-4b6f-a864-24fef277069b-image.png
Palindrome: a (Count=3)
0_1500788872920_61fc20cb-0cb2-4179-8f5a-529cbad7a2ec-image.png
Palindrome: No Palindrome

Third Loop:
0_1500788901120_bf12b13b-ff32-4703-86cf-0bcb54465428-image.png
Palindrome: b,aba,aabaa (Count=6)
0_1500788934388_5cc2c31d-404c-456a-a77d-1432bb0c679b-image.png
Palindrome: No Palindrome

Forth Loop:
0_1500788981884_a2d3f30e-0745-4a75-b2c0-940834bd6a84-image.png
Palindrome: a (Count=7)
0_1500789009429_f38aa5c2-17ac-47db-8fe9-b9bb4ceb1407-image.png
Palindrome: aa (Count=8)

Count = 9 (For the last character)

Answer = 9

 

int count =1;
public int countSubstrings(String s) {
    if(s.length()==0) 
        return 0;
    for(int i=0; i<s.length()-1; i++){
        checkPalindrome(s,i,i);     //To check the palindrome of odd length palindromic sub-string
        checkPalindrome(s,i,i+1);   //To check the palindrome of even length palindromic sub-string
    }
    return count;
}    

private void checkPalindrome(String s, int i, int j) {
    while(i>=0 && j<s.length() && s.charAt(i)==s.charAt(j)){    //Check for the palindrome string 
        count++;    //Increment the count if palindromin substring found
        i--;    //To trace string in left direction
        j++;    //To trace string in right direction
    }
}

 

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加和就是结果

 

An O(N) Solution (Manacher’s Algorithm):
First, we transform the input string, S, to another string T by inserting a special character ‘#’ in between letters. The reason for doing so will be immediately clear to you soon.

For example: S = “abaaba”, T = “#a#b#a#a#b#a#”.

To find the longest palindromic substring, we need to expand around each Ti such that Ti-d … Ti+d forms a palindrome. You should immediately see that d is the length of the palindrome itself centered at Ti.

We store intermediate result in an array P, where P[ i ] equals to the length of the palindrome centers at Ti. The longest palindromic substring would then be the maximum element in P.

Using the above example, we populate P as below (from left to right):

T = # a # b # a # a # b # a #
P = 0 1 0 3 0 1 6 1 0 3 0 1 0

Looking at P, we immediately see that the longest palindrome is “abaaba”, as indicated by P6 = 6.

public class Solution {
    public int countSubstrings(String s) {
        String rs = "#";
        //改造
        for(int i = 0; i < s.length(); i++) rs = rs + s.charAt(i) + "#";
        int[] RL = new int[rs.length()];//半径
        int pos = 0, maxRight = 0, count = 0;
        for(int i = 0; i < rs.length(); i++) {
            if(i < maxRight) {
                RL[i] = Math.min(maxRight - i, RL[2 * pos - i]);
            }
            while(i - RL[i] - 1 >= 0 && i + RL[i] + 1< rs.length() && rs.charAt(i - RL[i] - 1) == rs.charAt(i + RL[i] + 1)) {
                RL[i]++;
            }
            if(i + RL[i] > maxRight) {
                pos = i;
                maxRight = i + RL[i];
            }
            count += (RL[i] + 1) / 2;
        }
        return count;
    }
}

  

  

posted @ 2017-11-13 00:55  apanda009  阅读(159)  评论(0编辑  收藏  举报