想法是先求出h数组 然后对于每一个排名的后缀标记位置(属于哪一个串,就是那个col数组) 然后采用单调队列,每一次维护一个合法子区间:区间内包括所有的类型的col 但是WA #2
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<vector>
#include<map>
#include<queue>
#include<algorithm>
#define ll int
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=b;i>=a;--i)
using namespace std;
inline ll read()
{
ll x=0,f=1;
char c=getchar();
while (c<'0' || c>'9')
{
if (c=='-') f=-1;
c=getchar();
}
while (c>='0' && c<='9')
{
x=x*10+c-'0';
c=getchar();
}
return x*f;
}
inline void print(ll x)
{
if(x < 0) putchar('-'), x = -x;
if(x > 9) print(x / 10);
putchar(x % 10 + '0');
return ;
}
const int N = 1e5 + 7;
int rk[N << 1], sa[N], n, lstrk[N << 1], lstsa[N], w, m = 127, cnt[N], h[N], f[N][20];
char s[N << 1], s1[N << 1];
#define siz n * sizeof(int)
void init(){
m = 127;
memset(cnt, 0, sizeof cnt);
memset(sa, 0, siz);
memset(rk, 0, siz);
memset(h, 0, siz);
for(int i = 1; i <= n; ++i) ++cnt[rk[i] = s[i]];
for(int i = 1; i <= m; ++i) cnt[i] += cnt[i - 1];
for(int i = n; i >= 1; --i) sa[cnt[rk[i]]--] = i;
memcpy(lstrk + 1, rk + 1, siz);
for(int p = 0, i = 1; i <= n; ++i)
if(lstrk[sa[i]] == lstrk[sa[i - 1]])
rk[sa[i]] = p;
else
rk[sa[i]] = ++p;
for(w = 1; w < n; w <<= 1, m = n){
for(int p = 0, i = n; i >= n - w + 1; --i) lstsa[++p] = i;
for(int p = w, i = 1; i <= n; ++i)
if(sa[i] > w) lstsa[++p] = sa[i] - w;
memset(cnt, 0, sizeof cnt);
for(int i = 1; i <= n; ++i) ++cnt[rk[lstsa[i]]];
for(int i = 1; i <= m; ++i) cnt[i] += cnt[i - 1];
for(int i = n; i >= 1; --i) sa[cnt[rk[lstsa[i]]]--] = lstsa[i];
memcpy(lstrk + 1, rk + 1, siz);
for(int p = 0, i = 1; i <= n; ++i)
if(lstrk[sa[i]] == lstrk[sa[i - 1]] && lstrk[sa[i] + w] == lstrk[sa[i - 1] + w])
rk[sa[i]] = p;
else
rk[sa[i]] = ++p;
}
for(int i = 1, k = 0; i <= n; ++i){
if(rk[i] == 0) continue;
if(k) --k;
while(s[i + k] == s[sa[rk[i] - 1] + k]) ++k;
h[rk[i]] = k;
}
}
ll q[N] = {0}, hd = 0, tl = 0;
char S[10][3000];
int d[10];
int col[N];
void push(ll x){
while(tl > hd && h[q[tl]] > h[x]) tl--;
q[++tl] = x;
cnt[col[x]]++;
}
ll ans = 0;
void checkcnt(){
cout << "cnt: ";
for(int i = 1; i <= 5; ++i)
cout << cnt[i] << " "; puts("");
}
void checkqueue(){
cout << "queue: ";
for(int opt = hd + 1; opt <= tl; ++opt)
cout << q[opt] << " "; puts("");
}
ll l, r;
void cut(int x){
while(q[hd + 1] < x){
++hd;
}
}
int main(){
int T = read();
for(int i = 1; i <= T; ++i)
scanf("%s", S[i] + 1);
for(int i = 1; i <= T; ++i)
strcat(s + 1, S[i]+ 1), d[i] = strlen(s + 1);
n = strlen(s + 1);
if(T == 1){
print(n);
return 0;
}
init();
memset(cnt, 0, sizeof cnt);
for(int i = 1; i <= n; ++i){
for(int k = 1; k <= T; ++k){
if(sa[i] > d[k - 1] && sa[i] <= d[k])
col[i] = k;
}
}
q[++tl] = 2;
++cnt[col[1]];
++cnt[col[2]];
int i, tmp;
for(i = 3, tmp = (col[1] != col[2]) + 1; i <= n, tmp < T; ++i){
push(i);
if(cnt[col[i]] == 1) tmp++;
}
for(l = 2, r = i - 1; ;++l){
cut(l);
ans = max(ans, h[q[hd + 1]]);
-- cnt[col[l - 1]];
int suc = 1;
if(cnt[col[l - 1]] == 0){
suc = 0;
for(r = r + 1; r <= n; ++r){
push(r);
if(col[r] == col[l - 1]){
suc = 1;
break;
}
}
}
if(!suc) break;
}
print(ans); puts("");
return 0;
}