回文子串

原题在这里

  概述题意,问给定字符串s中有多少个子串是回文串,不同下标构成的子串视为不同子串。

analyse:

  1.暴力,数据范围只有1e3,substr+reverse暴力判断

code:

复制代码
class Solution
{
    bool check(string s)
    {
        string x = s;
        reverse(x.begin(), x.end());
        return x == s;
    }

public:
    int countSubstrings(string s)
    {
        /*
            analyse:
                尝试翻译为KMP:
                    末位跳转次数+len?
                len<=1000
                x
                肯定是有数据结构的规律的,但是这里就写暴力了
        */
        int ans = 0;
        for (int i = 0; i < s.length(); ++i)
            for (int j = s.length() - i; j > 0; --j)
                ans += check(s.substr(i, j));
        return ans;
    }
};
easy
复制代码

  2.中心拓展,但不是想当然式的两边+1+1那种,考虑中心的奇偶性,分为两种判断:

code:

复制代码
class Solution
{
    int ans = 0;
    int count(string s, int l, int r)
    {
        int num = 0;
        while (l >= 0 && r < s.length() && s[l] == s[r])
            ++num, --l, ++r;
        return num;
    }

public:
    int countSubstrings(string s)
    {
        for (int i = 0; i < s.length(); ++i)
            ans += count(s, i, i) + count(s, i, i + 1);
        return ans;
    }
};
mid
复制代码

  3.manacher,也属于是中心拓展,但是manacher会利用前面判断对后序判断进行优化,等于是中心拓展的优化。

关键点在于:对于manacher的中心数组p的使用,p[i]表示以i为中心的最长回文串半径,那么对于有多少个回文子串即为sum(p[i]/2)即可,因为p所处理的字符串为预处理过的字符串,所以单个字符构成的字符串并不计入在内。

code:

复制代码
class Solution
{
    string S;
    void Init(string s)
    {
        S = "~#";
        for (char i : s)
            S += i, S += '#';
    }
    int manacher(string s)
    {
        int mx = 0, id = 0, l = s.length();
        int ans = 0;
        // mx最大右端点,id最长回文串中心点
        vector<int> p(l);
        for (int i = 1; i < l; ++i)
        {
            if (mx > i)
                p[i] = min(mx - i, p[id - (i - id)]);
            else
                p[i] = 1;
            while (s[i - p[i]] == s[i + p[i]])
                ++p[i];
            if (p[i] + i > mx)
            {
                mx = p[i] + i;
                id = i;
            }
            ans += p[i] / 2;
        }
        return ans;
    }

public:
    int countSubstrings(string s)
    {
        /*
        analyse:
            翻译为manacher:
                p[i]表示以i为中心的最长回文串半径长度,那么最终ans=sum(p[i]/2)
        */
        Init(s);
        return manacher(S);
    }
};
复制代码

 

【Over】

posted @   Renhr  阅读(110)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
· 零经验选手,Compose 一天开发一款小游戏!
点击右上角即可分享
微信分享提示