• 字符串算法——manacher(马拉车)1/10


    manacher算法用处

    1.可以求一个字符串内最长回文字符串的长度,还能得到最长回文字符串是什么。

    2.可以求出一个字符串内有多少个回文字符串(同类型的算多个)。ps:如果要求不同类型回文字符串的数量可以使用dp,回文树,manacher+hash。

    时间复杂度

    因为在计算一个特定位置的答案时我们总会运行朴素算法,所以一眼看去该算法的时间复杂度为线性的事实并不显然。

    然而更仔细的分析显示出该算法具有线性复杂度。实际上,注意到朴素算法的每次迭代均会使r增加 1,以及 在算法运行过程中从不减小。这两个观察告诉我们朴素算法总共会进行 O(n) 次迭代。

    Manacher 算法的另一部分显然也是线性的,因此总复杂度为 O(n) 。

    form:[oiwiki](Manacher - OI Wiki (oi-wiki.org)

    原理

    参考该[博客](题解 P3805 [[模板]manacher算法] - 谁是鸽王 的博客 - 洛谷博客 (luogu.com.cn)

    核心思想就是利用已经暴力找到的回文串,加上回文串关于中心对称的性质,来快速得到部分回文字符串的长度,简化了暴力的规模。

    算法模板

    
    string s;//原串
    char str[N];//处理后的原串
    int p[N]//存储以每个点为中心的最长回文子串的半径
    int ans;//代表原串中最长的回文串的长度
    int sum;//代表原串中回文串的个数(同类型算多次)
    int init()//init操作可以让manacher同时求解奇数个数回文串和偶数个数回文串
    {
        int len=s.length();
        str[0]='^';
        str[1]='$';
        int j=2;
        for (int i=0;i
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    输出最长回文串模板

    void printSub(int C, int R){//C代表中心,R代表半径
        for(int i = C - R+1  ; i < C+ R;){
            cout<=1)
                printSub(k, p[k]);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    【模板】manacher 算法

    题目描述

    给出一个只由小写英文字符 $ \texttt a,\texttt b,\texttt c,\ldots\texttt y,\texttt z $ 组成的字符串 S S S ,求 S S S 中最长回文串的长度 。

    字符串长度为 n n n

    输入格式

    一行小写英文字符 a , b , c , ⋯   , y , z \texttt a,\texttt b,\texttt c,\cdots,\texttt y,\texttt z a,b,c,,y,z 组成的字符串 S S S

    输出格式

    一个整数表示答案。

    样例 #1

    样例输入 #1

    aaa
    
    • 1

    样例输出 #1

    3
    
    • 1

    提示

    1 ≤ n ≤ 1.1 × 1 0 7 1\le n\le 1.1\times 10^7 1n1.1×107

    AC代码

    const int N = 3e7;//因为N的范围问题,re了好几次,能开大最好开到最大,因为str需要两倍的空间
    char s[N];
    char str[N];
    int p[N];
    int init()
    {
    	int len=strlen(s);
    	str[0]='!';
    	str[1]='#';
    	int j=2;
    	for(int i=0;ir)
    		{
    			mid=i;
    			r=p[i]+i;
    		}
    		ans=max(ans,p[i]-1);
    	}
    	return ans;	
    }
    void solve()
    {
    	scanf("%s",s);
    	cout<
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    博客内容及模板仅供个人学习使用,如有错误,欢迎指正!

  • 相关阅读:
    后端大厂面试-15道题
    sql server卡慢问题定位和排查
    Hadoop Streaming使用简介
    【React】《React 学习手册 (第2版) 》笔记-Chapter3-JavaScript 函数式编程
    从餐桌到太空,孙宇晨的“星辰大海”
    【Android】源码中的工厂方法模式
    教你用canvas打造一个炫酷的碎片切图效果
    TDengine 入门教程——导读
    基于H5 网页的打豆豆小游戏的设计与实现
    http1,http1.1,http2及http3
  • 原文地址:https://blog.csdn.net/qq_57109165/article/details/126376454