Palindrome-(Manacher算法)

博客围绕求字符串的最长回文子串展开,给出题目链接,阐述题意为给定字符串求最长回文子串,解题思路是使用Manacher算法模板,最后给出代码。
题目链接:点击进入
题目

在这里插入图片描述
在这里插入图片描述

题意

给定一个字符串,求最长回文子串。

思路

Manacher算法模板

代码
#include<iostream>
#include<string>
#include<map>
//#include<unordered_map>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
#include<iomanip>
#include<cmath>
#include<fstream>
#include<stack>
#define X first
#define Y second
#define INF 0x3f3f3f3f
#define P pair<int,int>
using namespace std;
typedef long long ll;
const double eps=0.01;
const int N=1010;
const int maxn=2e6+10;
const int mod=1000000007;
int p[maxn],cnt;
char str[maxn];
void Manacher(string s,int len)
{
    int l=0;
    str[l++]='$';
    str[l++]='#';
    for(int i=0;i<len;i++)
	{
        str[l++]=s[i];
        str[l++]='#';
    }
    int mx=0,di=0;
    for(int i=0;i<l;i++)
	{
		if(i<mx) p[i]=min(p[2*di-i],mx-i);//i 在最远回文距离之内
		else p[i]=1;					  //i 在最远回文距离之外
		//左端点为'$',右端点为'\0',不需要边界判断
        //更新最大半径
        while(str[i+p[i]]==str[i-p[i]]) p[i]++;
        //如果最远半径增大,更新半径边界
        if(i+p[i]>mx)
		{
            mx=p[i]+i;
            di=i;
        }
    } 
}
int main()
{
	string s;
    while(cin>>s)
	{
        if(s=="END") break;
        int len=s.length();
        Manacher(s,len);
        int ans=0;
        for(int i=0;i<2*len+4;i++)
            ans=max(ans,p[i]-1);
        printf("Case %d: %d\n",++cnt,ans);
    }
    return 0;
}
Main-Lorentz 算法是一种用于查找字符串中所有回文子串的高效算法,其时间复杂度为线性,即 $ O(n) $,非常适合处理大规模字符串数据。该算法的核心思想是利用对称性质和扩展技巧来快速识别回文子串。 以下是 Main-Lorentz 算法的主要步骤: 1. **预处理字符串**:为了避免奇偶长度回文的分别处理,通常在字符之间插入特殊字符(例如 `#`),使得所有回文都变为奇数长度。 2. **使用数组记录回文半径**:维护一个数组 `P[i]`,表示以位置 `i` 为中心的最长回文子串的半径。 3. **利用对称性优化扩展**:通过维护当前已知的最远回文右边界和其中心,利用对称性减少不必要的重复计算。 4. **扩展回文子串**:对于每个中心位置,尝试扩展其回文半径,直到无法扩展为止。 下面是 Main-Lorentz 算法的 C++ 实现示例: ```cpp #include <iostream> #include <vector> #include <string> std::vector<int> manacherAlgorithm(const std::string& s) { std::string processed = "#"; for (char c : s) { processed += c; processed += "#"; } int n = processed.size(); std::vector<int> P(n, 0); int center = 0, right = 0; for (int i = 0; i < n; ++i) { int mirror = 2 * center - i; if (i < right) { P[i] = std::min(right - i, P[mirror]); } // 尝试扩展 int a = i + P[i] + 1; int b = i - P[i] - 1; while (a < n && b >= 0 && processed[a] == processed[b]) { P[i]++; a++; b--; } // 更新中心和右边界 if (i + P[i] > right) { center = i; right = i + P[i]; } } return P; } int main() { std::string input; std::cout << "Enter a string: "; std::cin >> input; std::vector<int> result = manacherAlgorithm(input); std::cout << "Palindrome radii: "; for (int r : result) { std::cout << r << " "; } std::cout << std::endl; return 0; } ``` ### 代码说明 - **预处理字符串**:通过在每个字符之间插入 `#` 来统一处理奇偶长度的回文。 - **维护中心和右边界**:通过维护当前已知的最远回文右边界和其中心,利用对称性减少不必要的重复计算。 - **扩展回文子串**:对于每个中心位置,尝试扩展其回文半径,直到无法扩展为止。 ### 算法复杂度分析 - **时间复杂度**:$ O(n) $,其中 $ n $ 是字符串的长度。每个字符的处理时间是常数,因此整体复杂度为线性。 - **空间复杂度**:$ O(n) $,用于存储回文半径的数组。 ### 应用场景 - **字符串处理**:Main-Lorentz 算法可以高效地查找字符串中的所有回文子串,适用于需要快速处理大规模字符串的场景。 - **数据压缩**:在某些数据压缩算法中,回文子串的检测可以用于优化压缩效率。 ### 相关问题 1. 如何优化 Main-Lorentz 算法以减少内存占用? 2. Main-Lorentz 算法在处理中文字符时需要注意哪些问题? 3. 如何将 Main-Lorentz 算法应用于查找最长回文子串?
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值