Leetcode 647 回文子串

题目描述:

给定一个字符串,你的任务是计算这个字符串中有多少个回文子串。

具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被计为是不同的子串。

示例 1:

输入: "abc"
输出: 3
解释: 三个回文子串: "a", "b", "c".

示例 2:

输入: "aaa"
输出: 6
说明: 6个回文子串: "a", "a", "a", "aa", "aa", "aaa".

注意:

  1. 输入的字符串长度不会超过1000。

思路:

进行遍历统计回文子串数,回文串分为奇数和偶数两种统计情况。

以一个数为中心,往外拓展,或者以两个数为中心,再向外拓展。

代码:

class Solution {
public:
    int countSubstrings(string s) {
        int len=s.size();
        int sum(len);
        for(int i=1;i<len-1;i++)//以i为中心拓展
        {
            int num=1;
            while(s[i-num]==s[i+num]&&i-num>=0&&i+num<len) 
            {sum++;num++;}            
        }
        for(int i=0;i<len-1;i++)//以i,i+1为中心拓展
        {
            int num=0;
            while(s[i-num]==s[i+1+num]&&i-num>=0&&i+num<len)
            {sum++;num++;}
        }
        return sum;
    }
};

第二种解法

这是从另一篇博客看到的

思路:先对字符串进行改造(例如原字符串是"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

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 @ 2018-10-03 11:42  qq874455953  阅读(136)  评论(0编辑  收藏  举报