关闭

//求一个串最多由哪个串复制若干次得到 poj 2406

366人阅读 评论(0) 收藏 举报

用kmp会很方便。

后缀数组的话枚举字符串(0,i),如果能够被n整除并且lcp(0,i+1)==n-i-1,那么答案就是n/(i+1);

//求一个串最多由哪个串复制若干次得到
#include <iostream>
#include <string>
#include <cmath>
#include <map>
using namespace std;
const int N=5000005;
int wa[N],wb[N],wv[N],wsum[N];
int height[N],sa[N],rank[N];
int n;
char str[N];
int f[N];
bool vis[N];
int r[N];
int ans;
#define F(x) ((x)/3+((x)%3==1?0:tb))
#define G(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2)
int c0(int *r,int a,int b)
{
	return r[a]==r[b]&&r[a+1]==r[b+1]&&r[a+2]==r[b+2];
}
int c12(int k,int *r,int a,int b)
{
	if(k==2)
		return r[a]<r[b]||r[a]==r[b]&&c12(1,r,a+1,b+1);
	else
		return r[a]<r[b]||r[a]==r[b]&&wv[a+1]<wv[b+1];
}
void sort(int *r,int *a,int *b,int n,int m)
{
    int i;
    for(i=0;i<n;i++) wv[i]=r[a[i]];
    for(i=0;i<m;i++) wsum[i]=0;
    for(i=0;i<n;i++) wsum[wv[i]]++;
    for(i=1;i<m;i++) wsum[i]+=wsum[i-1];
    for(i=n-1;i>=0;i--) b[--wsum[wv[i]]]=a[i];
    return;
}
void dc3(int *r,int *sa,int n,int m)
{
     int i,j,*rn=r+n,*san=sa+n,ta=0,tb=(n+1)/3,tbc=0,p;
     r[n]=r[n+1]=0;
     for(i=0;i<n;i++) if(i%3!=0) wa[tbc++]=i;
     sort(r+2,wa,wb,tbc,m);
     sort(r+1,wb,wa,tbc,m);
     sort(r,wa,wb,tbc,m);
     for(p=1,rn[F(wb[0])]=0,i=1;i<tbc;i++)
     rn[F(wb[i])]=c0(r,wb[i-1],wb[i])?p-1:p++;
     if(p<tbc) dc3(rn,san,tbc,p);
     else for(i=0;i<tbc;i++) san[rn[i]]=i;
     for(i=0;i<tbc;i++) if(san[i]<tb) wb[ta++]=san[i]*3;
     if(n%3==1) wb[ta++]=n-1;
     sort(r,wb,wa,ta,m);
     for(i=0;i<tbc;i++) wv[wb[i]=G(san[i])]=i;
     for(i=0,j=0,p=0;i<ta && j<tbc;p++)
     sa[p]=c12(wb[j]%3,r,wa[i],wb[j])?wa[i++]:wb[j++];
     for(;i<ta;p++) sa[p]=wa[i++];
     for(;j<tbc;p++) sa[p]=wb[j++];
     return;
}
void calheight(int *r,int *sa,int n)
{
	int i,j,k=0;
	for(i=0;i<=n;i++)
		rank[sa[i]]=i;
	for(i=0;i<n;height[rank[i++]]=k)
		for(k?k--:0,j=sa[rank[i]-1];r[i+k]==r[j+k];k++);
}
int mmin(int x,int y)
{
	return x<y?x:y;
}
/*void rmqinit(int n)
{
	int i,j,m,k;
	m=floor(log(1.0*n)/log(2.0));
	for(i=1;i<=n;i++)
		f[i][0]=height[i];
	for(i=1;i<=m;i++)
		for(j=n;j>=1;j--)
		{
			f[j][i]=f[j][i-1];
			k=1<<(i-1);
			if(j+k<=n)
				f[j][i]=mmin(f[j][i],f[j+k][i-1]);
		}
}*/
void rmqinit2(int n)
{
	int i,s=n-sa[rank[0]];
	for(i=rank[0];i>=1;i--)
	{
		f[i]=s;
		s=mmin(s,height[i]);
	}
	s=N;
	for(i=rank[0]+1;i<=n;i++)
	{
		s=mmin(s,height[i]);
		f[i]=s;
	}
}


/*int get_rmq(int x,int y)
{
	int m,t;
	x=rank[x];
	y=rank[y];
	if(x>y)  
        t=x,x=y,y=t;  
    x++;  
    m=floor(log(1.0*(y-x+1))/log(2.0));  
    return mmin(f[x][m],f[y-(1<<m)+1][m]);  
}*/


int main()
{
	int T,i,j,k,ca=0,s,t;
	scanf("%d",&T);
	while(~scanf("%s",str))
	{
		if(str[0]=='.')
			break;
		n=strlen(str);
		for(i=0;i<n;i++)  
			r[i]=(int)str[i]; 
		r[n]=0;
		dc3(r,sa,n+1,127);
		calheight(r,sa,n);
		rmqinit2(n);
		//for(i=1;i<=n;i++)
	//		cout<<i<<' '<<f[i]<<endl;
		for(i=0;i<n;i++)
			if(n%(i+1)==0)
			{
				s=f[rank[i+1]];
				if(s==n-i-1)
				{
					ans=n/(i+1);
					break;
				}
			}
		printf("%d\n",ans);
	}	
	return 0;
}


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:43715次
    • 积分:764
    • 等级:
    • 排名:千里之外
    • 原创:28篇
    • 转载:0篇
    • 译文:0篇
    • 评论:11条
    文章分类
    最新评论