题目:http://www.spoj.pl/problems/PHRASES/
把right[20]开成right[N],一直memset导致TLE;因为有字符串标记,所以字符串之间可以不用连接符;不过用连接符也可以。
还有da(arr,n+1,256)和calheight(arr,n),注意下标。
#include <cstdio> #include <cstring> #include <algorithm> #define clr(a,b) memset(a,b,sizeof(a)) using namespace std; const int N = 100000+100; const int inf = 0x3f3f3f3f; int ua[N], ub[N], us[N], sa[N], arr[N], at; int cmp(int *r, int a, int b, int l){ return r[a]==r[b]&&r[a+l]==r[b+l]; } void da(int *r, int n, int m){ int i, j, p, *x=ua, *y=ub, *t; for (i=0; i<m; i++) us[i] = 0; for (i=0; i<n; i++) us[x[i]=r[i]]++; for (i=1; i<m; i++) us[i]+=us[i-1]; for (i=n-1; i>=0; i--) sa[--us[x[i]]]=i; for (j=1,p=1; p<n; j*=2,m=p){ for (p=0,i=n-j; i<n; i++) y[p++]=i; for (i=0; i<n; i++) if (sa[i]>=j) y[p++]=sa[i]-j; for (i=0; i<m; i++) us[i]=0; for (i=0; i<n; i++) us[x[i]]++; for (i=1; i<m; i++) us[i]+=us[i-1]; for (i=n-1; i>=0; i--) sa[--us[x[y[i]]]]=y[i]; for (t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1; i<n; i++) x[sa[i]]=cmp(y, sa[i-1], sa[i], j)?p-1:p++; } } int rank[N], h[N]; void calh(int *r, int n){ int i, j, k = 0; for (i=1; i<=n; i++) rank[sa[i]]=i; for (i=0; i<n; h[rank[i++]]=k) for (k?k--:0,j=sa[rank[i]-1]; r[i+k]==r[j+k]; k++); } char str[N]; int n, left[20], right[20], f[N]; bool cal(int mid){ for (int j=0; j<n; j++){ if (right[j] - left[j] < mid) return false; } return true; } bool ok(int mid){ int k = 0, t; for (int i=1; i<=at; i++){ if (h[i] < mid){ if (k && cal(mid)) return true; k = 0; } else { if (k == 0){ clr(left, inf); clr(right, -1); t = f[sa[i-1]]; left[t] = right[t] = sa[i-1]; } t = f[sa[i]]; if (sa[i] < left[t]) left[t] = sa[i]; if (sa[i] > right[t]) right[t] = sa[i]; k = 1; } } if (k && cal(mid)) return true; return false; } int main(){ //freopen("D:/a.txt", "r", stdin); int T, l, mid, st, ed, ans; scanf("%d", &T); while (T--){ ans = at = st = 0; ed = inf; scanf("%d", &n); for (int i=0; i<n; i++){ scanf("%s", str); l = strlen(str), ed = min(ed, l); for (int j=0; j<=l; j++) arr[at] = (int)str[j], f[at++]=i; } da(arr, at, 256); calh(arr, at-1); while (st <= ed){ mid = st + (ed-st)/2; if (ok(mid)) ans = mid, st = mid+1; else ed= mid - 1; } printf("%d\n", ans); } return 0; }