回文字串——中心扩展算法

177 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第26天,点击查看活动详情


回文字串

给你一个字符串 s ,请你统计并返回这个字符串中 回文子串 的数目。

回文字符串 是正着读和倒过来读一样的字符串。

子字符串 是字符串中的由连续字符组成的一个序列。

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

 

示例 1:

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

示例 2:

输入: s = "aaa"
输出: 6
解释: 6个回文子串: "a", "a", "a", "aa", "aa", "aaa"

 

提示:

  • 1 <= s.length <= 1000
  • s 由小写英文字母组成

思路

该题目可作为最长回文字串的基础版,同样是需要求得回文字串,中心思想在于由一个中心轴开始向两边扩展,判断两个边界的字符是否相等,由于中心元素是确定的并且相等的,故不需要重复的判断中心字符串的回文性,只需要关注边界字符,提高了检索的效率。

具体而言,我们需要找到每个字符串的中心位置,当字符串长度为偶数个时,字符串是两两对称的,而字符串长度为奇数个时,字符串中心的字符可以为任意字符,其两侧的字符两两对称。

第一层遍历所有中心字符的情况,第二层由中心字符向两侧扩展,对于每个中心字符,需要考虑到字符串长度为奇数和偶数的情况。

题解

class Solution {
    public int countSubstrings(String s) {
        int cnt = 0;
        for(int i = 0; i < s.length(); i++) {
            int left = i, right = i;
            cnt += getCnt(s, i, i) + getCnt(s, i, i + 1);
        }
        return cnt;
    }

    private int getCnt(String s, int left, int right) {
        int cnt = 0;
        while(left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) {
            left--;
            right++;
            cnt++;
        }
        return cnt;
    }
}