首页 > 编程语言 >算法学习-Manacher

算法学习-Manacher

时间:2023-08-22 21:46:41浏览次数:38  
标签:中心 Manacher 学习 算法 sim ans 2j 回文

什么是 Manacher

Manacher 算法可以以 \(O(|S|)\) 的时间复杂度求出一个字符串的最长回文子串。

算法过程

令 \(k_i\) 为以 \(i\) 为回文中心向右扩展到的最远的位置(即若串 \(T_{l\sim r}\) 回文串,那么 \(T\) 的回文中心为 \(T_{\frac{l+r}{2}}\)),注意到偶数长度的串不具有回文中心,所以我们需要手动添加一些不在字符集里的特殊字符来人为制造回文中心。

具体的,对于一个字符串 \(S_{1\sim n}\),将每对相邻字符间和字符串两侧放入不在字符集里的相同字符(如#),将 \(S_{1\sim n}\to S'_{1\sim 2n-1}\),然后给字符串的开头或者末尾中的一处添加另一种特殊字符,如@

例子:\(S=\)cjwenandmasterhuangakioi,\(S'=\)@#c#j#w#e#n#a#n#d#m#a#s#t#e#r#h#u#a#n#g#a#k#i#o#i#

那么若已经求出 \(k_{1\sim i-1}\),如何求出 \(k_i\) 呢?

注意到回文串有一个很好性质,那就是回文(

所以说,有 \(\forall j, k_j\ge i,j<i\),\(k_i\ge \min(i+k_{2j-i}-(2j-i),k_j)\)

画个图理解一下:

img

若以 \(2j-i\) 为回文中心的回文串并没有超过 \(j\) 为回文中心的回文串,那么啥事没有,\(k_i=i+k_{2j-i}-(2j-i)\) 即可。

若以 \(2j-i\) 为回文中心的回文串超过了 \(j\) 为回文中心的回文串,那么超过部分并不能算作 \(k_i\) 的答案,因为 \(S_{k_j+1} \neq S_{2k_j-j-1}\),所以答案应当回缩为 \(2k_j-j\),对称一下就是 \(k_j\) 了。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N = 1.1e7 + 5;
char s0[N], s[N << 1];
int n0, n, r, m, ans, k[N << 1];

signed main()
{
    ios::sync_with_stdio(0);cin.tie(0);
    
    cin >> s0 + 1;
    n0 = strlen(s0 + 1);
    s[0] = '_';
    for(int i = 1; i <= n0; i ++)
        s[(i << 1) - 1] = '#', s[i << 1] = s0[i];
    s[n0 << 1 | 1] = '#';

    n = strlen(s + 1);
    for(int i = 1; i <= n; i ++)
    {
        if(i <= r) k[i] = min(r, i + k[(m << 1) - i] - (m << 1) + i);
        else k[i] = i;
        while(s[k[i] + 1] == s[(i << 1) - k[i] - 1]) k[i] ++;
        if(k[i] >= r) r = k[i], m = i;
        ans = ans < k[i] - i ? k[i] - i : ans;
    }
    cout << ans;

    return 0;
}

标签:中心,Manacher,学习,算法,sim,ans,2j,回文
From: https://www.cnblogs.com/adam01/p/17649763.html

相关文章

  • ArcMap栅格重采样:最邻近分配、众数算法、双线性插值、三次卷积插值
      本文介绍在ArcMap软件中,实现栅格图像重采样的具体操作,以及不同重采样方法的选择依据。  在文章ArcPy批量掩膜、重采样大量遥感影像中,我们介绍了基于Python中Arcpy模块对栅格图像加以批量重采样的方法;而在ArcMap软件中,我们可以实现不需要代码的栅格重采样操作;本文就对这一操......
  • 雪花算法单线程实现-scala
    雪花算法单线程实现-scala参考blog/***[时间戳][数据标识id][机器id]*/objectSnowFlake{//开始时间(ms)2023-08-0100:00:00privatevalstartTimestamp=1690819200000L//机器id所占的位数privatevalworkerIdBits=5L//数据标识id所占的位......
  • Markdown学习笔记
    标题语法标准语法要创建标题,只需要在单词或者短语钱添加井号#。井号的个数代表标题的级别,支持1~6个级别可选语法可以在文本下方添加任意数量的=号来标识一级标题,或者-号来标识二级标题最佳实践为了兼容各类应用程序#和标题之间使用一个空格来分割段落(段落1)使用......
  • 网络编程学习01
    一、进程间通信-socket套接字(很重要,函数啥的都要求要能背)基本特征:socket是一种接口技术,被抽象了一种文件的操作,可以让同一计算机中的不同进程之间通信,也可以让不同计算机中的进程之间通信(网络通信)本地进程间通信编程模型:进程A进程B创建so......
  • 学习C语言第一天
    循环语句和分支语句#include<stdio.h>intmain(){ //输出1~100之间的奇数循环语句的两种表达方式 inti=1; //for(inti=1;i<=100;i++) //{ // if(i%2==1) // { // printf("%d\n",i); // } //} while(i<=100) { if(i%2==1) printf("......
  • 02.前后端分离中台框架前端 admin.ui.plus 学习-介绍与简单使用
    中台框架前台项目admin.ui.plus的初识基于vue3.x+CompositionAPIsetup语法糖+typescript+vite+elementplus+vue-router-next+pinia技术,内置支持一键生成微服务接口,适配手机、平板、pc的后台权限管理框架,希望减少工作量,帮助大家实现快速开发。框架一览......
  • Java学习io流总结
    一、IO的分类按照流向分输入流Input输出流Output按照传输数据的类型来分字节流字节输入:InputStream字节输出:OutputStream字符流字符输入流:Reader字符输出流:Writer按照流连接的目标来分节点流:低级流-->程序(内存)直接连接源文件包装流:高级......
  • [基础] 学习笔记
    1.重载运算符structnode{ intx; booloperator<(constnode&a)const { returnx>a.x;//从小到大 }};priority_queue<node>q;structcmp{ booloperator()(constint&a,constint&b) { ... }};priority_queue&l......
  • C++学习day01
    C++学习day01一、C++介绍本贾尼.斯特劳斯特卢普,于1979年在贝尔实验室负责分析UNIX系统内核流量的分布情况时,特别希望有一种更加模块化的工具,于1979.10开始着手研发一款新的编程语言,在C语言的基础上增加了面向对象的机制,也就是C++,1983年完成了C++的第一个版本C++与C的关联和重要......
  • 算法学习-exKMP
    什么是exKMPexKMP(Z-Algorithm)是一个可以在\(O(|S|+|T|)\)的时间复杂度内求出\(T\)串的每个后缀与\(T\)的LCP(最长公共前缀)\(T\)串和\(S\)串每个后缀的LCP。的算法。算法过程首先回忆一下KMP算法,求\(nxt\)数组和两串匹配本质上没啥区别。所以我们尝试也将......