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

原创 2012年03月22日 18:49:21

用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;
}


poj 1743 后缀数组+二分答案 求一个串的最长无重叠的重复出现次数最多的子串

Description A musical melody is represented as a sequence of N (1
  • winycg
  • winycg
  • 2016年11月04日 19:30
  • 152

poj 2406 后缀数组dc3 板子 计算出现次数最多的循环节 dc3 板子

题意:给你一个串,该串可以由其一个子串重复k’次形成,让你求的k的最大值 正解应该是 kmp 题意:给你一个串,该串可以由其一个子串重复k’次形成,让你求的k的最大值 思路:首先得思想是枚举k然后...

poj 2406 kmp求连续重复子串的个数

Power Strings Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 33119   ...

poj 2406 求连续重复子串出现的次数 后缀数组

Power Strings Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 26591   ...

判断一个串是否为某个基本串的简单复制构成的

public class Test1 { /* * 代码的目标:判断一个串是否为某个基本串的简单复制构成的。 * 例如: * abcabcabc,它由“abc”复制3次构成,则...
  • aaygj
  • aaygj
  • 2013年06月01日 20:23
  • 788

求一个串中出现的第一个最长重复子串

/* ** ** 求一个串中出现的第一个最长重复子串。采用顺序结构存储串,实现求串s中出现的第一个最长重复子串的下标和长度 ** */ #include #include using names...
  • wbxcww
  • wbxcww
  • 2011年10月16日 10:42
  • 1482

求一个串中出现的第一个最长可重叠重复子串 [后缀数组解法]

http://blog.csdn.net/iamskying/article/details/4759485   题目描述: 求一个串中出现的第一个最长重复子串 采用顺序结...

识别复制串 判断一个串是否为某个基本串的简单复制构成的。

/* 识别复制串 代码的目标:判断一个串是否为某个基本串的简单复制构成的。 例如: abcabcabc,它由“abc”复制3次构成,则程序输出:abc aa 由“a”复制两次构成,则程...

poj2406--Power Strings+KMP求周期

先把结论摆出来:对于长为j的字符串str[1..j],next[j]=k,则令d=j-k;如果j%d==0,则这个字符串是一个 周期串,前d个字符是其最小的循环结,共包含j/d个循环节。 现在来解...
  • acm_lkl
  • acm_lkl
  • 2015年02月07日 15:49
  • 444

poj2406—KMP next数组的性质求最小周期

题目大意:给出一个字符串,求它最多有几个连续子串构成 分析:KMP求最小周期——结论:如果一个字符串有最小周期,那么最小周期为n-next[n] 考虑整个串,根据next数组的定义,前后匹配并且前...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章://求一个串最多由哪个串复制若干次得到 poj 2406
举报原因:
原因补充:

(最多只允许输入30个字)