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

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

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

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

    Sample Input 1
    abacaba

    Sample Output 1
    7

    Sample Input 2
    www

    Sample Output 2
    4

    HINT
    (lvert s vert) 表示字符串 s 的长度。
    数据满足1≤ (lvert s vert) ≤300000。


    SA+Manacher

    首先对原串处理出Height数组,同时求出以每个点作为回文中心所能扩张的最大长度

    然后暴力枚举,对于每个作为回文中心的点,枚举回文串长度,然后在Height数组上二分,求出L,R,那么R-L+1就是出现次数

    然后这样会TLE

    考虑一个贪心的思想,对于每个作为回文串最左/右端的点,我们直接使用最大扩张长度即可

    至于正确性?如果存在较小的长度使得其可以出现两次,那么我们必然可以在第二次出现的地方枚举到这种情况

    然后注意求区间Height最小值,不能用线段树(可能会TLE),应该使用RMQ,复杂度为(O(nlog n))

    (然而我代码里写的是作为回文中心的……随手Hack,但是过了)

    /*program from Wolfycz*/
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define inf 0x7f7f7f7f
    using namespace std;
    typedef long long ll;
    typedef unsigned int ui;
    typedef unsigned long long ull;
    inline char gc(){
    	static char buf[1000000],*p1=buf,*p2=buf;
    	return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
    }
    inline int frd(){
    	int x=0,f=1;char ch=gc();
    	for (;ch<'0'||ch>'9';ch=gc())	if (ch=='-')	f=-1;
    	for (;ch>='0'&&ch<='9';ch=gc())	x=(x<<1)+(x<<3)+ch-'0';
    	return x*f;
    }
    inline int read(){
    	int x=0,f=1;char ch=getchar();
    	for (;ch<'0'||ch>'9';ch=getchar())	if (ch=='-')	f=-1;
    	for (;ch>='0'&&ch<='9';ch=getchar())	x=(x<<1)+(x<<3)+ch-'0';
    	return x*f;
    }
    inline void print(int x){
    	if (x<0)	putchar('-'),x=-x;
    	if (x>9)	print(x/10);
    	putchar(x%10+'0');
    }
    const int N=3e5;
    int n,m=26;
    bool ck(int *r,int x,int y,int l){return r[x]==r[y]&&r[x+l]==r[y+l];}
    void Suffix_sort(int *A,int *SA){
    	static int sum[N+10],buf[N+10];
    	memset(buf,0,sizeof(buf));
    	int *x=A,*y=buf;
    	for (int i=1;i<=m;i++)	sum[i]=0;
    	for (int i=1;i<=n;i++)	sum[x[i]]++;
    	for (int i=1;i<=m;i++)	sum[i]+=sum[i-1];
    	for (int i=n;i>0;i--)	SA[sum[x[i]]--]=i;
    	for (int l=1,p=0,top=0;p<n;l<<=1,m=p,top=0){
    		for (int i=n-l+1;i<=n;i++)	y[++top]=i;
    		for (int i=1;i<=n;i++)	if (SA[i]>l)	y[++top]=SA[i]-l;
    		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>0;i--)	SA[sum[x[y[i]]]--]=y[i];
    		swap(x,y),x[SA[1]]=p=1;
    		for (int i=2;i<=n;i++)	x[SA[i]]=ck(y,SA[i-1],SA[i],l)?p:++p;
    	}
    }
    int A[N+10],SA[N+10],Rank[N+10],H[N+10],p[(N<<1)+10];
    void Get_height(char *s){
    	for (int i=1,k=0,j;i<=n;H[Rank[i++]]=k)
    	for (k?k--:0,j=SA[Rank[i]-1];s[i+k]==s[j+k];k++);
    }
    void Manacher(char *s){
    	static char T[(N<<1)+10];
    	for (int i=1;i<=n;i++)	T[i<<1]=s[i],T[i<<1|1]='#';
    	int len=n<<1|1;
    	T[0]='%',T[1]='#',T[len+1]='$';
    	int Max=0,ID=0;
    	for (int i=1;i<=len;i++){
    		p[i]=Max>i?min(p[ID*2-i],Max-i):1;
    		while (T[i+p[i]]==T[i-p[i]])	p[i]++;
    		if (i+p[i]>Max)	Max=i+p[ID=i];
    	}
    }
    int rmq[20][N+10],g[N+10];
    void RMQ(){
    	for (int i=1;i<=n;i++)	rmq[0][i]=H[i];
    	for (int j=1;j<20;j++)
    		for (int i=1;i<=n;i++)
    			if (i+(1<<j)-1<=n)
    				rmq[j][i]=min(rmq[j-1][i],rmq[j-1][i+(1<<(j-1))]);
    	for (int i=2;i<=n;i++)	g[i]=g[i-1]+(2<<g[i-1]<=i);
    }
    bool check(int l,int r,int k){
    	int jp=g[r-l],tmp=min(rmq[jp][l+1],rmq[jp][r-(1<<jp)+1]);
    	return tmp>=k;
    }
    int work(int x,int len){
    	int L,R,l,r;
    	l=1,r=x-1;
    	while (l<=r){
    		int mid=(l+r)>>1;
    		if (check(mid,x,len))	r=mid-1;
    		else	l=mid+1;
    	}L=l;
    	l=x+1,r=n;
    	while (l<=r){
    		int mid=(l+r)>>1;
    		if (check(x,mid,len))	l=mid+1;
    		else	r=mid-1;
    	}R=r;
    	return R-L+1;
    }
    int main(){
    	static char s[N+10];
    	scanf("%s",s+1);
    	n=strlen(s+1);
    	for (int i=1;i<=n;i++)	A[i]=s[i]-'a'+1;
    	Suffix_sort(A,SA);
    	for (int i=1;i<=n;i++)	Rank[SA[i]]=i;
    	Get_height(s),RMQ();
    	Manacher(s);
    	ll Ans=0;
    	for (int i=1;i<=(n<<1|1);i++){
    		if (p[i]==1)	continue;
    		int x=(i>>1)-(p[i]>>1)+1;
    		Ans=max(Ans,1ll*work(Rank[x],p[i]-1)*(p[i]-1));
    	}
    	printf("%lld
    ",Ans);
    	return 0;
    }
    
  • 相关阅读:
    objective-c内存管理中autorelease的作用
    objective-c在Xcode中@property相关参数的解释
    objective-c中的内存管理
    c#扩展方法-摘自msdn
    objective-c中的category
    c语言中结构体的定义、初始化及内存分配
    c语言中的结构体为值类型,当把一个结构体赋值给另一个结构体时,为值传递
    手动通过Lucene判断该pom文件中jar是否存在,子依赖没判断
    代码方式删除SVN
    Maven多层嵌套
  • 原文地址:https://www.cnblogs.com/Wolfycz/p/10578316.html
Copyright © 2011-2022 走看看