ZOJ 3199 Longest Repeated Substring

来源:互联网 发布:js获取项目相对路径 编辑:程序博客网 时间:2024/06/04 19:21

转载请注明出处:http://blog.csdn.net/drecik__/article/details/7409101

/* * 套用大神的后缀数组模板做的; * 不过第一次还是很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 50005int 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[n] ; 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;}