[APIO2014]回文串

摘要:
标题只使用(sam)真是太好了。对于原始字符串,建立后缀自动机,然后建立反向字符串以进行匹配。发现我们会遇到这种情况。这里,(mx)是蓝色部分最靠后的位置。我们画一个正字符串。我们的反向字符串是红色位置,可以匹配蓝色位置。所以我们反转红色的位置,它可以与蓝色相匹配。然后(S[l]=S[mx],S[l+1]=S[mx-1]…)我们可以得出结论,([l,mx])这里是回文字符串跳转(链接),这将减少匹配长度,

题目

只使用(sam)的做法真是太妙了

对于原串建立后缀自动机,之后将反串放上去匹配,发现我们会得到这样的情况

图

这里的(mx)是蓝色部分出现最靠后的位置

我们画的这是一个正串,我们的反串就是红色位置,和蓝色位置能产生匹配

于是我们把红色位置倒过来,就能和蓝色匹配

于是(S[l]=S[mx],S[l+1]=S[mx-1]...)

于是我们就可以断定([l,mx])这里是一个回文串

(link)会使得匹配长度减小,但是出现次数增加,所以我们还需要跳一波(link)

为什么是(maxpos)呢,这样是为了在其最后一次出现的时候统计所有本质不同的回文子串

如果前面有一段和红色部分相同的,那么就不会重复统计了

代码

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define re register
#define LL long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
const int maxn=6e5+5;
inline int read() {
	char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
	while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
}
int n,lst=1,cnt=1;
char S[maxn>>1];
int len[maxn],fa[maxn],son[maxn][26],pos[maxn],vis[maxn];
int A[maxn],tax[maxn>>1];LL sz[maxn];
LL ans;
inline void ins(int c,int o) {
	int p=++cnt,f=lst;lst=p;
	len[p]=len[f]+1,sz[p]=1;pos[p]=o;
	while(f&&!son[f][c]) son[f][c]=p,f=fa[f];
	if(!f) {fa[p]=1;return;}
	int x=son[f][c];
	if(len[f]+1==len[x]) {fa[p]=x;return;}
	int y=++cnt;
	len[y]=len[f]+1,fa[y]=fa[x],fa[x]=fa[p]=y;
	for(re int i=0;i<26;i++) son[y][i]=son[x][i];
	while(f&&son[f][c]==x) son[f][c]=y,f=fa[f];
}
int main() {
	scanf("%s",S+1);n=strlen(S+1);
	for(re int i=1;i<=n;i++) ins(S[i]-'a',i);
	for(re int i=1;i<=cnt;i++) tax[len[i]]++;
	for(re int i=1;i<=n;i++) tax[i]+=tax[i-1];
	for(re int i=cnt;i>=0;--i) A[tax[len[i]]--]=i;
	for(re int i=cnt;i>=0;--i) {
		int x=A[i];
		sz[fa[x]]+=sz[x];pos[fa[x]]=max(pos[x],pos[fa[x]]);
	}
	int now=1,l=0;
	for(re int i=n;i;--i) {
		while(now&&!son[now][S[i]-'a']) 
			now=fa[now],l=len[now];
		if(!now) {now=1;l=0;continue;}
		if(son[now][S[i]-'a']) 
			now=son[now][S[i]-'a'],l++;
		if(pos[now]<=i+l-1) {
			if(pos[now]>=i) ans=max(ans,(LL)(pos[now]-i+1)*sz[now]);
			for(re int k=fa[now];!vis[k]&&k;k=fa[k]) {
				if(pos[k]<=i+len[k]-1) 
					ans=max(ans,(LL)(pos[k]-i+1)*sz[k]);
				else break;
			}
		}
	}
	printf("%lld
",ans);
	return 0;
}

免责声明:文章转载自《[APIO2014]回文串》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇koa 上传图片,上传文件,批量上传文件,批量上传图片...java学习笔记hibernate基础(1)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

随便看看

jmeter监控内存,CPU等方法

当然,我们也可以选择本地进程下的远程进程来获取服务器的内存使用情况和其他信息。在文本框中输入需要测试的服务器的IP地址:port,然后在下面输入用户名和密码。单击“连接”以查看发生的情况。...

SQLserver 获取当前时间

选择CONVERT(varchar,GETDATE())--2017selectDATENAME(YEAR,GETDATE())--2017selectDATEPART。获取当前月份--05或5selectDATENAME(MM,...

故障排查:vsftpd无法用浏览器访问

CentOS6上设置的ftp服务器突然无法使用浏览器访问,但可以使用xftp等工具正常访问。据推测,阿里云的安全组设置之前已经过修改,这可能与1)修改vsftpd的配置,在被动模式下手动指定一个随机连接端口,并添加以下内容:passv_min_port=50000pasv_max_port=60000 02)如果只打开端口20和21,设置阿里云安全组控制端口...

element-ui表格el-table回显时默认全选数据

1、html代码˂el-table-columntype="selection"width="45"...

前端导航站点(PC端)

本篇LIST1.项目预览地址:项目预览地址2.项目完成效果:3.HTML布局拆分1.tip提示部分2.title标题部分3.搜索栏部分找的是codepen上现成的搜索框样式,包含搜索框展开收缩的特效。...

nginx做本地目录映射

nginx做本地目录映射有时候需要访问服务器上的一些静态资源,比如挂载其他设备上的图片到本地的目录,而本地的目录不在nginx根目录下,这个时候就需要简单的做一下目录映射来解决,比如想通过浏览器http://ip/image/2016/04/29/10/abc.jpg访问到系统目录/image_data/2016/04/29/10/abc.jpg需要在ngi...