试题描述

输入一个字符串S,输出S的最长连续回文子串长度。

输入
输入一个字符串S。
输出
输出S的最长连续回文子串长度
输入示例
abacbbc
输出示例
4
其他说明
1<=|S|<=1000000

这就是传说中的萌萌哒马拉车算法(manacher)啦

首先为了方便处奇偶两种情况,将S重新变成新的字符串T,如abacddc变成#a#b#a#c#d#d#c#

再次为了方便处理越界,将字符串首尾加一个奇怪的不匹配字符,如将abacddc变成~#a#b#a#c#d#d#c#`

请大家想一想这样的好处

考虑暴力算法,枚举回文串中心,暴力向两边匹配

rep(,n-) {
int t=;
while(s[i-t]==s[i+t]) t++;
ans=max(ans,t-);
}

这样是O(N^2),考虑优化

我们定义P[i]表示位置i的最长匹配长度,考虑利用之前的匹配信息。

这样就是p[i]=p[2*id-i]

这样就是p[i]=mx-i

写成代码就是这样

#include<cstdio>
#include<cctype>
#include<queue>
#include<cstring>
#include<algorithm>
#define rep(s,t) for(int i=s;i<=t;i++)
#define ren for(int i=first[x];i!=-1;i=next[i])
using namespace std;
inline int read() {
int x=,f=;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-;
for(;isdigit(c);c=getchar()) x=x*+c-'';
return x*f;
}
const int maxn=;
char s[maxn];
int p[maxn];
int solve(char* s2) {
int n=,id=,mx=,ans=;
for(int i=;s2[i]!='\0';i++) s[n++]='#',s[n++]=s2[i];
s[]='~';s[n++]='#';s[n++]='`';
rep(,n-) {
if(mx>i) p[i]=min(p[*id-i],mx-i);
else p[i]=;
while(s[i+p[i]]==s[i-p[i]]) p[i]++;
if(i+p[i]>mx) mx=i+p[i],id=i;
ans=max(ans,p[i]-);
}
return ans;
}
char s2[maxn];
int main() {
scanf("%s",s2);
printf("%d\n",solve(s2));
return ;
}

为什么是O(N)的呢?

因为算法只有遇到还没有匹配的位置时才进行匹配,已经匹配过的位置不再进行匹配,所以对于T字符串中的每一个位置,只进行一次匹配,所以Manacher算法的总体时间复杂度为O(n),其中n为T字符串的长度,由于T的长度事实上是S的两倍,所以时间复杂度依然是线性的。

补一个PAM的(以后不能装*,将”f[np]=to[k][c];to[p][c]=np;“i写成”f[to[p][c]=np]=to[k][c];“就会T飞,因为k可能等于p)

#include<cstdio>
#include<cctype>
#include<queue>
#include<cstring>
#include<algorithm>
#define rep(s,t) for(int i=s;i<=t;i++)
#define ren for(int i=first[x];i!=-1;i=next[i])
using namespace std;
inline int read() {
int x=,f=;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-;
for(;isdigit(c);c=getchar()) x=x*+c-'';
return x*f;
}
const int maxn=;
char ch[maxn];
struct PAM {
int cnt,last;
int to[maxn][],f[maxn],l[maxn];
PAM() {cnt=f[]=;l[]=-;}
void extend(int c,int n) {
int p=last;
while(ch[n]!=ch[n-l[p]-]) p=f[p];
if(!to[p][c]) {
int np=++cnt,k=f[p];l[np]=l[p]+;
while(ch[n]!=ch[n-l[k]-]) k=f[k];
f[np]=to[k][c];to[p][c]=np;
}
last=to[p][c];
}
int solve() {
int ans=;
rep(,cnt) ans=max(ans,l[i]);
return ans;
}
}sol;
int main() {
scanf("%s",ch+);int n=strlen(ch+);
rep(,n) sol.extend(ch[i]-'a',i);
printf("%d\n",sol.solve());
return ;
}

COJ977 WZJ的数据结构(负二十三)的更多相关文章

  1. COJ 1002 WZJ的数据结构(二)(splay模板)

    我的LCC,LCT,Splay格式终于统一起来了... 另外..这个形式的Splay是标准的Splay(怎么鉴别呢?看Splay函数是否只传了一个变量node就行),刘汝佳小白书的Splay写的真是不 ...

  2. [COJ0988]WZJ的数据结构(负十二)

    [COJ0988]WZJ的数据结构(负十二) 试题描述 输入 见题目,注意本题不能用文件输入输出 输出 见题目,注意本题不能用文件输入输出 输入示例 输出示例 数据规模及约定 1≤N≤1500,M≤N ...

  3. COJ967 WZJ的数据结构(负三十三)

    WZJ的数据结构(负三十三) 难度级别:C: 运行时间限制:7000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 请你设计一个数据结构,完成以下功能: 给定一个大 ...

  4. COJ968 WZJ的数据结构(负三十二)

    WZJ的数据结构(负三十二) 难度级别:D: 运行时间限制:5000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 给你一棵N个点的无根树,边上均有权值,每个点上有 ...

  5. COJ 0967 WZJ的数据结构(负三十三)

    WZJ的数据结构(负三十三) 难度级别:E: 运行时间限制:7000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 请你设计一个数据结构,完成以下功能: 给定一个大 ...

  6. COJ 0979 WZJ的数据结构(负二十一)

    WZJ的数据结构(负二十一) 难度级别:C: 运行时间限制:5000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 请你实现一个数据结构,完成这样的功能: 给你一个 ...

  7. [COJ0968]WZJ的数据结构(负三十二)

    [COJ0968]WZJ的数据结构(负三十二) 试题描述 给你一棵N个点的无根树,边上均有权值,每个点上有一盏灯,初始均亮着.请你设计一个数据结构,回答M次操作. 1 x:将节点x上的灯拉一次,即亮变 ...

  8. [COJ0985]WZJ的数据结构(负十五)

    [COJ0985]WZJ的数据结构(负十五) 试题描述 CHX有一个问题想问问大家.给你一个长度为N的数列A,请你找到两个位置L,R,使得A[L].A[L+1].…….A[R]中没有重复的数,输出R- ...

  9. [COJ0989]WZJ的数据结构(负十一)

    [COJ0989]WZJ的数据结构(负十一) 试题描述 给出以下定义: 1.若子序列[L,R]的极差(最大值-最小值)<=M,则子序列[L,R]为一个均匀序列. 2.均匀序列[L,R]的权值为S ...

随机推荐

  1. bash read命令用法

    read -p "Enter your student ID: " USERNAMEread -s -p "Enter your password: " PAS ...

  2. 【OpenStack】OpenStack系列12之OpenStack自动化测试详解

    参考文档: https://github.com/yongluo2013/osf-openstack-training/blob/master/installation/How-to-setup-op ...

  3. 【leetcode】Sort List

    Sort List Sort a linked list in O(n log n) time using constant space complexity.   需要采用归并排序对链表进行操作. ...

  4. Android 向Application对象添加Activity监听

    可以建立对象把Application.ActivityLifecycleCallbacks接口中的函数实现,并利用public void registerActivityLifecycleCallba ...

  5. android 初探

    2014年7月27日 15:02:57 附: android 官方培训课程中文版 //官方简单的入门教程, 每个大类中只介绍了几个知识点, 可以快速搭建一个hello world android 开发 ...

  6. codeforces 476C.Dreamoon and Sums 解题报告

    题目链接:http://codeforces.com/problemset/problem/476/C 题目意思:给出两个数:a 和 b,要求算出 (x/b) / (x%b) == k,其中 k 的取 ...

  7. mybatis配置文件xml中插入新数据

    初用mybatis,发现很好的一个操作数据库的框架,里面有一些小技巧,挺简单,很实用,记录一下: mybatis的插入语句: <insert id="insertAsset" ...

  8. SQLHelper、DBUtil终极封装

    DBUtil.java package org.guangsoft.util; import java.io.InputStream; import java.sql.Connection; impo ...

  9. Timer&TimerTask原理分析

    转载地址,请珍惜作者的劳动成果,转载请注明出处:http://www.open-open.com/lib/view/open1337176725619.html 如果你使用Java语言进行开发,对于定 ...

  10. C语言中的break、continue和goto三者的区别与用法

    exit的话是在stdlib的头文件里面定义的,他是的程序退出,正如exit的字面意思一样break的话是终止当前循环继续进行循环后面的语句,但是程序照样还在进行只能while switch for中 ...