zoukankan      html  css  js  c++  java
  • Jzoj3654 【APIO2014】回文串

    题意:求出现次数*长度最大的回文串

    很水的一道题直接用回文树可以切了

    太菜并不会回文树,用了极慢的sam+manacher

    manacher求出所有回文子串用sam在parent树上面倍增就可以求出一个串的出现次数,manacher是O(n)的,倍增lgn,整体复杂度nlgn

    (分开的manacher比什么插入特殊符号的好写多了)

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #define N 600010
    using namespace std;
    char str[N]; long long A=0;
    int s[N][26],mx[N],f[N],sz[N],pos[N];
    int n,cnt=1,lst=1,v[N],r[N],p[N][20],b[N];
    int extend(char c,int r){
    	int p=lst,np=lst=++cnt,q,nq; 
    	c-='a'; mx[np]=mx[p]+1; sz[np]=1; pos[r]=np;
    	for(;p&&!s[p][c];p=f[p]) s[p][c]=np;
    	if(!p) return f[np]=1; q=s[p][c];
    	if(mx[q]==mx[p]+1) f[np]=q;
    	else{
    		nq=++cnt; mx[nq]=mx[p]+1;
    		f[nq]=f[q]; f[q]=f[np]=nq;
    		memcpy(s[nq],s[q],26<<2);
    		for(;p&&s[p][c]==q;p=f[p]) s[p][c]=nq;
    	}
    }
    inline void query(int l,int r){
    	int x=pos[r];
    	for(int j=19;~j;--j)
    		if(mx[p[x][j]]>=r-l+1) x=p[x][j];
    	A=max(A,(r-l+1ll)*sz[x]);
    }
    int main(){
    	freopen("palindrome.in","r",stdin);
    	freopen("palindrome.out","w",stdout);
    	scanf("%s",str+1); n=strlen(str+1);
    	for(int i=1;i<=n;++i) extend(str[i],i);
    	for(int i=1;i<=cnt;++i) ++v[mx[i]];
    	for(int i=1;i<=n;++i) v[i]+=v[i-1];
    	for(int i=cnt;i;--i) r[v[mx[i]]--]=i;
    	for(int x,i=cnt;i;--i){
    		x=r[i];
    		sz[f[x]]+=sz[x];
    	}
    	for(int i=1,x;i<=cnt;++i){
    		x=r[i]; p[x][0]=f[x];
    		for(int j=1;j<20;++j) p[x][j]=p[p[x][j-1]][j-1];
    	}
    	int mx=0,id; *str='+'; str[n+1]='*';
    	for(int i=1;i<=n;++i){
    		if(mx>i) b[i]=min(mx-i,b[2*id-i-1]);
    		else b[i]=0;
    		for(;str[i+b[i]+1]==str[i-b[i]];++b[i]) query(i-b[i],i+b[i]+1);
    		if(b[i]+i>mx) mx=b[i]+i,id=i;
    	}
    	mx=0;
    	for(int i=1;i<=n;++i){
    		if(mx>i) b[i]=min(mx-i-1,b[2*id-i]);
    		else { b[i]=1; query(i,i); }
    		for(;str[i+b[i]]==str[i-b[i]];++b[i]) query(i-b[i],i+b[i]);
    		if(b[i]+i>mx) mx=b[i]+i,id=i;
    	}
    	printf("%lld
    ",A);
    }
    Pam的后面学了再补上

  • 相关阅读:
    mysql 历史版本下载
    mysql 5.7 版本 You must reset your password using ALTER USER statement before executing this statement报错处理
    5.7 zip 版本的安装 以及遇到的坑
    mysql 5.6zip版本的卸载与5.7 zip 版本的安装
    mysql数据库的备份与还原
    本地Navicat连接docker里的mysql
    docker修改数据库密码
    docker 在push镜像到本地registry出现的500 Internal Server Error
    linux 没有界面内容显示不全解决办法
    json与map互相转换
  • 原文地址:https://www.cnblogs.com/Extended-Ash/p/9477298.html
Copyright © 2011-2022 走看看