28.leetCode647:Palindromic Substrings

来源:互联网 发布:马云否认淘宝是日本的 编辑:程序博客网 时间:2024/05/16 04:31

题目
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

题意:给定一个字符串,找出该字符串中有多少子字符串是回文。

思路一:逐一找出每个子字符串并判断该子字符串是否为回文。

代码

class Solution {    public int countSubstrings(String s) {        int count=0;        char[] cs = s.toCharArray();        for(int i=0;i<cs.length;i++){            StringBuilder newString = new StringBuilder();            StringBuilder reverse = new StringBuilder();            for(int j=i;j<cs.length;j++){                newString.append(cs[j]);                reverse.insert(0,cs[j]);                if(newString.toString().equals(reverse.toString()))                    count++;            }        }       return count;     }}

运行时间:446ms

思路二:所有的回文串都是对称的。长度为奇数回文串以最中间字符的位置为对称轴左右对称,而长度为偶数的回文串的对称轴在中间两个字符之间的空隙。可否利用这种对称性来提高算法效率呢?答案是肯定的。我们知道整个字符串中的所有字符,以及字符间的空隙,都可能是某个回文子串的对称轴位置。可以遍历这些位置,在每个位置上同时向左和向右扩展,直到左右两边的字符不同,或者达到边界。

代码

class Solution {    public int countSubstrings(String s) {        if(s.length()==0 || s==null)            return 0;        int count = 0;        for(int i=0;i<s.length();i++){            count += countSubstrings(s,i,i);            count += countSubstrings(s,i,i+1);        }        return count;    }    public int countSubstrings(String s, int left, int right){        int count = 0;        while(left>=0 && right<s.length() && s.charAt(left)== s.charAt(right)){            count++;            left--;            right++;        }        return count;    }}

运行时间:11ms

思路三:利用马拉车算法(用于计算最长的回文串)。先对字符串进行改造(例如原字符串是”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加和就是结果。
如:
char: # a # b # a #
RL : 1 2 1 4 1 2 1
i : 0 1 2 3 4 5 6
以b为中心时, 半径为4,所含回文串数目是(4+1)/2 = 2,即b,aba

马拉车的参考资料
1.[https://segmentfault.com/a/1190000003914228
2.http://www.cnblogs.com/grandyang/p/4475985.html
3.http://blog.csdn.net/dyx404514/article/details/42061017

代码

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

运行时间:23ms

原创粉丝点击