zoukankan      html  css  js  c++  java
  • 【洛谷P3805】【模板】manacher算法

    题目

    题目链接:https://www.luogu.com.cn/problem/P3805
    给出一个只由小写英文字符 \(\texttt a,\texttt b,\texttt c,\ldots\texttt y,\texttt z\) 组成的字符串 \(S\) ,求 \(S\) 中最长回文串的长度 。

    字符串长度为 \(n\)

    思路

    先将每两个字母之间插入一个奇怪的符号。
    \(p[x]\) 表示第 \(x\) 个字符为对称中心,能扩展的最远距离是多少。记 \(mid,mr\) 分别为所有便利过的区间中右端点最远时的对称中心和右端点最大值。

    • \(x\leq mr\) 时,显然 \(p[x]=min(p[x],2\times mid-x)\)
    • \(x>mr\) 时,暴力扩展即可。
      由于 \(mid\) 单调增,所以时间复杂度 \(O(n)\)

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N=11000010;
    int n,p[N*2];
    char s[N*2];
    
    int manacher(char *s)
    {
    	int ans=0,mid=0,mr=0;
    	for (int i=2;i<n;i++)
    	{
    		if (i<=mr) p[i]=min(p[mid*2-i],mr-i+1);
    		while (s[i-p[i]-1]==s[i+p[i]+1]) p[i]++;
    		if (i+p[i]-1>mr) mid=i,mr=i+p[i]-1;
    		ans=max(ans,p[i]);
    	}
    	return ans;
    }
    
    int main()
    {
    	scanf("%s",s+1);
    	n=strlen(s+1);
    	for (int i=n*2;i>=1;i-=2) s[i]=s[i/2];
    	for (int i=n*2-1;i>=1;i-=2) s[i]='#';
    	s[n*2+1]=s[0]='#'; n=n*2+1;
    	printf("%d",manacher(s));
    	return 0;
    }
    
  • 相关阅读:
    三元判断大小奇偶
    键盘输入 循环 for if-else while 等循环
    三元 导包
    进制
    符号等
    第二模块 4.1 模块的种类和介绍
    第二模块 练习题
    第二模块 3.15 迭代器
    第二模块 3.14 通过生成器实现并发编程
    第二模块 3.13 生成器
  • 原文地址:https://www.cnblogs.com/stoorz/p/13765457.html
Copyright © 2011-2022 走看看