您的位置:首页 > 其它

ZOJ 3199 Longest Repeated Substring

2012-03-29 22:01 155 查看
转载请注明出处:/article/3712459.html

/*
 * 套用大神的后缀数组模板做的;
 * 不过第一次还是很SB的TLE了一次, 哎;
 */

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
using namespace std;

#define ABS( a ) ( (a) >= 0? (a) : -(a) )

typedef long long LL;

//ranks从0开始
//sa从1开始,因为最后一个字符(最小的)排在第0位;
//high从2开始,因为表示的是sa[i-1]和sa[i];
#define M 50005
int ranks[M],sa[M],X[M],Y[M],high[M];
char init[M];
int buc[M];
void calhigh(int n) {
	int i , j , k = 0;
	for(i = 1 ; i <= n ; i++) ranks[sa[i]] = i;
	for(i = 0 ; i < n ; high[ranks[i++]] = k)
		for(k?k--:0 , j = sa[ranks[i]-1] ; init[i+k] == init[j+k] ; k++);
}
bool cmp(int *r,int a,int b,int l) {
	return (r[a] == r[b] && r[a+l] == r[b+l]);
}
void suffix(int n,int m = 128) {
	int i , l , p , *x = X , *y = Y;
	for(i = 0 ; i < m ; i ++) buc[i] = 0;
	for(i = 0 ; i < n ; i ++) buc[ x[i] = init[i]  ] ++;
	for(i = 1 ; i < m ; i ++) buc[i] += buc[i-1];
	for(i = n - 1; i >= 0 ; i --) sa[ --buc[ x[i] ]] = i;
	for(l = 1,p = 1 ; p < n ; m = p , l *= 2) {
		p = 0;
		for(i = n-l ; i < n ; i ++) y[p++] = i;
		for(i = 0 ; i < n ; i ++) if(sa[i] >= l) y[p++] = sa[i] - l;
		for(i = 0 ; i < m ; i ++) buc[i] = 0;
		for(i = 0 ; i < n ; i ++) buc[ x[y[i]] ] ++;
		for(i = 1 ; i < m ; i ++) buc[i] += buc[i-1];
		for(i = n - 1; i >= 0 ; i --) sa[ --buc[ x[y[i]] ] ] = y[i];
		for(swap(x,y) , x[sa[0]] = 0 , i = 1 , p = 1 ; i < n ; i ++)
			x[ sa[i] ] = cmp(y,sa[i-1],sa[i],l) ? p-1 : p++;
	}
	calhigh(n-1);//后缀数组关键是求出high,所以求sa的时候顺便把ranks和high求出来;
}
//当需要反复询问两个后缀的最长公共前缀时用到RMQ;
int Log[M];
int best[20][M];
void initRMQ(int n) {//初始化RMQ;
	for(int i = 1; i <= n ; i ++) best[0][i] = high[i];
	for(int i = 1; i <= Log
 ; i ++) {
		int limit = n - (1<<i) + 1;
		for(int j = 1; j <= limit ; j ++) {
			best[i][j] = min(best[i-1][j] , best[i-1][j+(1<<i>>1)]);
		}
	}
}
int lcp(int a,int b) {//询问a,b后缀的最长公共前缀;
	a = ranks[a];	b = ranks[b];
	if(a > b) swap(a,b);
	a ++;
	int t = Log[b - a + 1];
	return min(best[t][a] , best[t][b - (1<<t) + 1]);
}

void solve()
{
	int len = strlen( init )+1;

	suffix(len);
	//initRMQ(len);

	int maxLen = 0;

	for ( int i = 2; i < len; ++i )
	{
		if ( ABS(sa[i-1] - sa[i]) == high[i] )
		{
			if ( high[i] > maxLen )
				maxLen = high[i];
		}
	}

	cout << maxLen << endl;
}

int main() {
	//预处理每个数字的Log值,常数优化,用于RMQ;
	/*Log[0] = -1;
	for(int i = 1; i <= M ; i ++) {
		Log[i] = (i&(i-1)) ? Log[i-1] : Log[i-1] + 1 ;
	}*/
	//*******************************************
	//	n为数组长度,下标0开始;
	//	将初始数据,保存在init里,并且保证每个数字都比0大;
	//	m = max{ init[i] } + 1
	//	一般情况下大多是字符操作,所以128足够了;
	//*******************************************

	int t;
	scanf( "%d", &t );
	while ( t-- )
	{
		scanf( "%s", init );

		solve();
	}

	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: