ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

luogu P3649 [APIO2014]回文串

2022-03-27 22:32:21  阅读:167  来源: 互联网

标签:Le La luogu P3649 APIO2014 son && Fi define


题面传送门
结合manacher的拓展过程以及复杂度证明可以知道,一个序列的本质不同回文串是\(O(n)\)个,并且每次拓展时会出现一个可能本质不同的字符串。
那么就把这个回文串扔到SAM上查出现次数就好了。时间复杂度\(O(n\log n)\)
如果这样那也就不会有这篇题解了。
但是问题在于空间开不下。主要空间有\(O(n|\sum|)\)的SAM和\(O(n\log n)\)的倍增。
我先把SAM换成map,因为据说SAM的转移数是不超过\(3n-2\)的,但是好像map的空间不咋地,常数很大。
然后我又把倍增砍了一半,即大于\(2^9\)的暴力跳,小于\(2^9\)的再倍增,这样空间砍了一半,时间差不多是\(O(n\sqrt n)\)的。就可以过了。
code:

#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define RI re int
#define ll long long
#define db double
#define lb long db
#define N (600000+5)
#define M (100+5)
#define K (200000+5)
#define mod 998244353
#define Mod (mod-1)
#define eps (1e-9)
#define U unsigned int
#define it iterator
#define Gc() getchar() 
#define Me(x,y) memset(x,y,sizeof(x))
#define Mc(x,y) memcpy(x,y,sizeof(x))
#define d(x,y) (n*(x-1)+(y))
#define R(n) (rand()*rand()%(n)+1)
#define Pc(x) putchar(x)
#define LB lower_bound
#define UB upper_bound
#define PB push_back
using namespace std;
int n,m,k,H,lg[N],Id[N],ToT,Mid,Len,F[N];ll Ans;char A[N],S[N];
namespace SAM{
	int La=1,p,q,cnt=1,Le[N],son[N][26],Fi[N],fa[N][10],d[N],Si[N];vector<int> S[N];I void Ins(int x){
		p=La;Le[La=++cnt]=Le[p]+1;Si[La]=1;while(p&&!son[p][x]) son[p][x]=La,p=Fi[p];if(!p) {Fi[La]=1;return;}q=son[p][x];if(Le[q]==Le[p]+1){Fi[La]=q;return;}
		Le[++cnt]=Le[p]+1;Mc(son[cnt],son[q]);Fi[cnt]=Fi[q];Fi[La]=Fi[q]=cnt;while(p&&son[p][x]==q) son[p][x]=cnt,p=Fi[p];
	}
	I void dfs(int x,int La){d[x]=d[La]+1;fa[x][0]=La;for(RI i=1;fa[x][i-1]&&i<10;i++) fa[x][i]=fa[fa[x][i-1]][i-1];for(RI i:S[x]) dfs(i,x),Si[x]+=Si[i];}
	I void BD(){for(RI i=2;i<=cnt;i++) S[Fi[i]].PB(i);dfs(1,0);}
	I int Jp(int x,int Len){while(Le[fa[x][9]]>=Len) x=fa[x][9];for(RI i=lg[d[x]];~i;i--) fa[x][i]&&Le[fa[x][i]]>=Len&&(x=fa[x][i]);return Si[x];}
}
int main(){
	freopen("1.in","r",stdin);
	RI i;scanf("%s",A+1);n=strlen(A+1);S[H=1]='$';S[H=2]='#';for(i=1;i<=n;i++) S[++H]=A[i],S[++H]='#',SAM::Ins(A[i]-'a'),Id[i]=SAM::La;S[++H]='&';
	for(i=2;i<=n*2;i++) lg[i]=lg[i/2]+1;Mid=1;SAM::BD();for(i=2;i<=H;i++){
		Mid+Len>=i&&(F[i]=min(F[2*Mid-i],Mid+Len-i));while(S[i+F[i]]==S[i-F[i]]) S[i-F[i]]^'#'&&(ToT=SAM::Jp(Id[(i+F[i]-1)/2],F[i]+1),Ans=max(Ans,1ll*ToT*(F[i]+1))),F[i]++;
		i+F[i]>Mid+Len&&(Mid=i,Len=F[i]);
	}printf("%lld\n",Ans);
}

标签:Le,La,luogu,P3649,APIO2014,son,&&,Fi,define
来源: https://www.cnblogs.com/275307894a/p/16064920.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有