码迷,mamicode.com
首页 > 编程语言 > 详细

【后缀数组】poj2406 Power Strings

时间:2015-04-28 13:21:14      阅读:166      评论:0      收藏:0      [点我收藏+]

标签:

连续重复子串(pku2406)
给定一个字符串 L,已知这个字符串是由某个字符串 S 重复 R 次而得到的,
求 R 的最大值。
算法分析:
做法比较简单,穷举字符串 S 的长度 k,然后判断是否满足。判断的时候,
先看字符串 L 的长度能否被 k 整除,再看 suffix(1)和 suffix(k+1)的最长公共
前缀是否等于 n-k。在询问最长公共前缀的时候, suffix(1)是固定的,所以 RMQ
问题没有必要做所有的预处理,只需求出 height 数组中的每一个数到
height[rank[1]]之间的最小值即可。整个做法的时间复杂度为 O(n)。

卡倍增……

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define N 1000001
char s[N];
int n,tong[N],t[N],t2[N],sa[N],rank[N],lcp[N];
bool cmp(int y[],int i,int k)
{
	return ((y[sa[i-1]]==y[sa[i]])&&((sa[i-1]+k>=n?-1:y[sa[i-1]+k])==(sa[i]+k>=n?-1:y[sa[i]+k])));
}
void build_sa(int range)
{
	int *x=t,*y=t2;
	memset(tong,0,sizeof(int)*range);
	for(int i=0;i<n;++i) tong[x[i]=s[i]]++;
	for(int i=1;i<range;++i) tong[i]+=tong[i-1];
	for(int i=n-1;i>=0;--i) sa[--tong[x[i]]]=i;
	for(int k=1;k<=n;k<<=1)
	  {
	  	int p=0;
	  	for(int i=n-k;i<n;++i) y[p++]=i;
	  	for(int i=0;i<n;++i) if(sa[i]>=k) y[p++]=sa[i]-k;
		memset(tong,0,sizeof(int)*range);
		for(int i=0;i<n;++i) tong[x[y[i]]]++;
		for(int i=1;i<range;++i) tong[i]+=tong[i-1];
		for(int i=n-1;i>=0;--i) sa[--tong[x[y[i]]]]=y[i];
	  	swap(x,y); p=1; x[sa[0]]=0;
	  	for(int i=1;i<n;++i) x[sa[i]]=cmp(y,i,k)?p-1:p++;
	  	if(p>=n) break;
	  	range=p;
	  }
}
void get_lcp()
{
	int k=0;
	for(int i=0;i<n;++i) rank[sa[i]]=i;
	for(int i=0;i<n;++i) if(rank[i])
	  {
	  	if(k) --k;
	  	int j=sa[rank[i]-1];
	  	while(s[i+k]==s[j+k]) ++k;
	  	lcp[rank[i]]=k;
	  }
}
int query[N];
int main()
{
	while(1)
	  {
	  	scanf("%s",s);
	  	if(s[0]==‘.‘) break;
	  	n=strlen(s);
	  	build_sa(128);
	  	get_lcp();
	  	int minv=n-sa[rank[0]];
	  	for(int i=rank[0];i>=0;--i)
	  	  {
	  	  	query[i]=minv;
	  	  	minv=min(minv,lcp[i]);
	  	  }
	  	minv=lcp[rank[0]+1];
	  	for(int i=rank[0]+1;i<n;++i)
	  	  {
	  	  	query[i]=minv;
	  	  	minv=min(minv,lcp[i+1]);
	  	  }
	  	query[rank[n]]=0;
	  	for(int i=1;i<=n;++i)
	  	  if(n%i==0&&query[rank[i]]==n-i)
	  	    {
	  	      printf("%d\n",n/i);
	  	      break;
	  	    }
	  }
	return 0;
}

【后缀数组】poj2406 Power Strings

标签:

原文地址:http://www.cnblogs.com/autsky-jadek/p/4462559.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!