zoukankan      html  css  js  c++  java
  • [bzoj3676] [APIO2014]回文串

    Description

    考虑一个只包含小写拉丁字母的字符串s。我们定义s的一个子串t的“出
    现值”为t在s中的出现次数乘以t的长度。请你求出s的所有回文子串中的最
    大出现值。

    Input

    输入只有一行,为一个只包含小写字母(a -z)的非空字符串s。

    Output

    输出一个整数,为回文子串的最大出现值。

    Sample Input

    abacaba 
    

    Sample Output

    7 
    

    Solution

    SA+manacher。

    考虑(manacher)的过程中,本质不同的回文串只会在每次扩展的时候出现,所以每次扩展的时候上下二分,然后算一下就好了。

    复杂度(O(nlog n))

    注意(manacher)之前会把原串翻倍,在翻倍之前就把(sa)建好,否则卡不过。。

    (其实这题正解是回文自动机来着。。那玩意貌似是O(n)的)

    #pragma GCC optimize(3)
    #include<bits/stdc++.h>
    using namespace std;
     
    void read(int &x) {
        x=0;int f=1;char ch=getchar();
        for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
        for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
    }
    
    #define ll long long 
     
    void print(ll x) {
        if(x<0) putchar('-'),x=-x;
        if(!x) return ;print(x/10),putchar(x%10+48);
    }
    void write(ll x) {if(!x) putchar('0');else print(x);putchar('
    ');}
    
    const int maxn = 6e5+10;
    
    char c[maxn],s[maxn];
    int n,f[maxn];
    ll ans;
    
    int spx[maxn],spy[maxn],sum[maxn],sa[maxn],m,rk[maxn],height[maxn],st[maxn][20],lg[maxn],len;
    
    void get_sa() {
    	m=240;int p=0,*x=spx,*y=spy;
    	for(int i=1;i<=n;i++) sum[x[i]=c[i]]++;
    	for(int i=1;i<=m;i++) sum[i]+=sum[i-1];
    	for(int i=n;i;i--) sa[sum[x[i]]--]=i;
    	
    	for(int tot=0,k=1;p<n;k<<=1,tot=0) {
    		p=0;
    		for(int i=n-k+1;i<=n;i++) y[++tot]=i;
    		for(int i=1;i<=n;i++) if(sa[i]>k) y[++tot]=sa[i]-k;
    
    		for(int i=1;i<=m;i++) sum[i]=0;
    		for(int i=1;i<=n;i++) sum[x[y[i]]]++;
    		for(int i=1;i<=m;i++) sum[i]+=sum[i-1];
    		for(int i=n;i;i--) sa[sum[x[y[i]]]--]=y[i];
    
    		swap(x,y);x[sa[1]]=p=1;
    		for(int i=2;i<=n;i++)
    			if(y[sa[i]]!=y[sa[i-1]]||y[sa[i]+k]!=y[sa[i-1]+k]) x[sa[i]]=++p;
    			else x[sa[i]]=p;
    		m=n;
    	}
    }
    
    void get_height() {
    	for(int i=1;i<=n;i++) rk[sa[i]]=i;
    	int p=1;
    	for(int i=1;i<=n;i++) {
    		if(p) p--;
    		while(c[i+p]==c[sa[rk[i]-1]+p]) p++;
    		height[rk[i]]=p;
    	}
    }
    
    void rmq_init() {
    	for(int i=1;i<=n;i++) st[i][0]=height[i];
    	for(int i=2;i<=n;i++) lg[i]=lg[i>>1]+1;
    	for(int i=1;i<=18;i++)
    		for(int j=1;j<=n;j++)
    			st[j][i]=min(st[j][i-1],st[j+(1<<(i-1))][i-1]);
    }
    
    int get_rmq(int l,int r) {
    	if(r<l) return r=l;
    	int w=lg[r-l+1];
    	return min(st[l][w],st[r-(1<<w)+1][w]);
    }
    
    void get_ans(int lpos,int rpos,int xx) {
    	if(s[lpos]=='&') return ;
    	lpos/=2,rpos/=2;
    	int w=rk[lpos];
    	int l=1,r=w,ret=w,mid,Len=rpos-lpos+1;
    	while(l<=r) {
    		mid=(l+r)>>1;
    		if(get_rmq(mid+1,w)>=Len) ret=mid,r=mid-1;
    		else l=mid+1;
    	}
    	int ret2=w;l=w,r=len;
    	while(l<=r) {
    		mid=(l+r)>>1;
    		if(get_rmq(w+1,mid)>=Len) ret2=mid,l=mid+1;
    		else r=mid-1;
    	}
    	ans=max(ans,1ll*(ret2-ret+1)*xx);
    }
    
    int main() {
    	char e=getchar();
    	while(e!=EOF&&e!='
    ') c[++len]=e,e=getchar();
    	
    	n=len;get_sa(),get_height(),rmq_init();
    
    	s[n=0]='$',s[++n]='&';
    	for(int i=1;i<=len;i++) s[++n]=c[i],s[++n]='&';
    	
    	int mr=1,mid=1;
    	for(int i=1;i<=n;i++) {
    		f[i]=min(mr-i,f[mid*2-i]);
    		while(s[i-f[i]]==s[i+f[i]]) get_ans(i-f[i],i+f[i],f[i]+1),f[i]++;
    		if(i+f[i]>mr) mr=i+f[i],mid=i;
    	}
    	write(ans);
    	return 0;
    }
    
  • 相关阅读:
    luffy-短信接口频率限制,以及前端发送,和注册
    腾讯云短信开发
    luffy-登录注册页面
    vue之vue-cookies 获取、设置以及删除指定的cookies
    pycharm操作git
    luffy的前端主页
    vue路由跳转的方式
    django 中的Model继承
    跨域请求CORS详解
    vue:实现图书购物车
  • 原文地址:https://www.cnblogs.com/hbyer/p/10284595.html
Copyright © 2011-2022 走看看