记录编号 378829 评测结果 AAAAAAAAAA
题目名称 [HZOI 2016] 寒假ing 最终得分 100
用户昵称 Gravatarrewine 是否通过 通过
代码语言 C++ 运行时间 2.211 s
提交时间 2017-03-05 08:27:24 内存使用 43.91 MiB
显示代码纯文本
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

void read(int &x) {
	char c;bool flag(0);
	while((c=getchar())<'0'||c>'9') flag |= c=='-';
	x=c-'0';while((c=getchar())>='0'&&c<='9') x=(x<<1)+(x<<3)+c-'0';
	flag ? x=-x:x;
}

using namespace std;

#define N 401000

#define All for(int i = 0; i < n; i++)

void radix(int *s,int *a,int *b,int n,int m) {
    static int c[N];
    for (int i = 0; i <= m; i++) c[i] = 0;
    for (int i = 0; i < n; i++) ++c[s[a[i]]];
    for (int i = 1; i <= m; i++) c[i] += c[i-1];
	for (int i = n-1; i >= 0; i--) b[--c[s[a[i]]]] = a[i];
}

void suffix(int *s,int *sa,int n,int m) {
    static int rk[N],a[N],b[N];
	for (int i = 0; i < n; i++) rk[i] = i;
	radix(s,rk,sa,n,m); rk[sa[0]] = 0;
	for (int i = 1; i < n; i++)
	 rk[sa[i]] = rk[sa[i-1]]+(s[sa[i-1]]==s[sa[i]]?0:1);
	for (int i = 0; 1<<i < n; i++) {
		for (int j = 0; j < n; j++) {
			a[j] = rk[j]+1;	sa[j] = j;
			b[j] = j+(1<<i)>=n?0:rk[j+(1<<i)]+1;
		}
		radix(b,sa,rk,n,n); radix(a,rk,sa,n,n);
		rk[sa[0]] = 0;
		for (int j = 1; j < n; j++)
		 rk[sa[j]] = rk[sa[j-1]]+(a[sa[j-1]]==a[sa[j]]&&b[sa[j-1]]==b[sa[j]]?0:1);
	}
}

void calc_ht(int *s,int *sa,int *ht,int *rk,int n) {
    int k = 0,j;  ht[0] = 0;
	for (int i = 0; i < n; i++) rk[sa[i]] = i;
	for (int i = 0; i < n; i++) {
	   k?--k:0; j = sa[rk[i]-1];
	   if(!rk[i]) k = 0;
	   else while(s[i+k] == s[j+k]) k++;
       ht[rk[i]] = k;
	}
}


char s1[N],s2[N];
int sa[N],rk[N],h[N],a[N],n,f[N][20];

void st_init() {
	for (int i = 0; i < n; i++) f[i][0] = h[i];
	for (int i = 1; 1<<i < n; i++)
	 for (int j = 0; j+(1<<i)-1 < n; j++)
	  f[j][i] = min(f[j][i-1],f[j+(1<<i-1)][i-1]);
}

int Lcp(int l,int r) {
	l = rk[l]; r = rk[r];
	if(l > r) swap(l,r); l++;
	int k = 0;
	while(1<<k+1 <= r-l+1) k++;
	return min(f[l][k],f[r-(1<<k)+1][k]);
}

int calc(int L) {
	int tmp = 1,ans = 1;
	for (int i = 0; i+L < n; i += L) {
		int R = Lcp(i,i+L);
		ans = max(ans,R/L+1);
		if(i-L+R%L >= 0)
	 	  ans = max(ans,Lcp(i-L+R%L,i+R%L)/L+1);
	}
	return ans;
}

int main() {
    freopen("broken.in","r",stdin); freopen("broken.out","w",stdout);
    int _;
    for(read(_); _; --_) {
	    read(n); scanf("%s",s1);
	    copy(s1,s1+n,a);
	    suffix(a,sa,n,256);
	    calc_ht(a,sa,h,rk,n);
	    st_init();
	    int ans = 0;
	    for (int i = 1; i <= n; i++) ans = max(ans,calc(i));
	    printf("%d\n",ans);
	}
	return 0;
}