647. 回文子串

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

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

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

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/palindromic-substrings
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

中心拓展

class Solution {
    private int count(String s, int l, int r) {
        int ans = 0;
        while (l >= 0 && r < s.length() && s.charAt(l) == s.charAt(r)) {
            --l;
            ++r;
            ans++;
        }
        return ans;
    }

    public int countSubstrings(String s) {
        int n = s.length(), ans = 0;
        for (int i = 0; i < n; ++i) {
            ans += count(s, i, i);
            ans += count(s, i, i + 1);
        }
        return ans;
    }
}

Manacher

import java.util.Scanner;

class Solution {

    private char[] getManacher(String s) {
        char[] res = new char[s.length() * 2 + 1];
        for (int i = 0; i < s.length(); ++i) {
            res[i * 2] = '#';
            res[i * 2 + 1] = s.charAt(i);
        }
        res[res.length - 1] = '#';
        return res;
    }

    public int countSubstrings(String s) {
        if (s == null || s.length() == 0) {
            return 0;
        }

        char[] manacher = getManacher(s);
        int ret = 0;
        int r = -1, c = 0;
        int[] p = new int[manacher.length];
        for (int i = 0; i < manacher.length; ++i) {
            p[i] = i > r ? 1 : Math.min(p[2 * c - i], r - i + 1);
            while (i + p[i] < manacher.length && i - p[i] >= 0 && manacher[i + p[i]] == manacher[i - p[i]]) {
                p[i]++;
            }


            ret += p[i] / 2;

            if (i + p[i] - 1 > r) {
                r = i + p[i] - 1;
                c = i;
            }
        }

        return ret;
    }

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while (in.hasNext()) {
            System.out.println(new Solution().countSubstrings(in.next()));
        }
    }
}
posted @ 2021-12-24 17:54  Tianyiya  阅读(37)  评论(0)    收藏  举报