传送门:http://hihocoder.com/problemset/problem/1415
【题解】
考虑求出两串合在一起(中间加分隔符)后缀数组,就是要求任意在两个串中的$i, j$,$\min\{h_k\} (i \leq k \leq j)$的最大值。
考虑$i, j$一定是满足$|i - j| = 1$且合法的时候最优。
详情见:hihocoder“解题方法提示”
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
# include <stdio.h> # include <string.h> # include <iostream> # include <algorithm> // # include <bits/stdc++.h> using namespace std; typedef long long ll; typedef long double ld; typedef unsigned long long ull; const int M = 5e5 + 10; const int mod = 1e9+7; # define rank RANK int n, ans; char ch[M]; int sa[M], rank[M], h[M], t[M]; int tsa[M], cntA[M], cntB[M], A[M], B[M]; inline void getsa() { fill(cntA, cntA + n + 1, 0); for (int i=1; i<=n; ++i) cntA[ch[i]] ++; for (int i=1; i<=n; ++i) cntA[i] += cntA[i-1]; for (int i=n; i; --i) sa[cntA[ch[i]] --] = i; rank[sa[1]] = 1; for (int i=2; i<=n; ++i) { rank[sa[i]] = rank[sa[i-1]]; if(ch[sa[i-1]] != ch[sa[i]]) ++rank[sa[i]]; } for (int len=1; rank[sa[n]] < n; len <<= 1) { fill(cntA, cntA + n + 1, 0); fill(cntB, cntB + n + 1, 0); for (int i=1; i<=n; ++i) { cntA[A[i] = rank[i]] ++; cntB[B[i] = ((i+len<=n) ? rank[i+len] : 0)] ++; } for (int i=1; i<=n; ++i) cntA[i] += cntA[i-1], cntB[i] += cntB[i-1]; for (int i=n; i; --i) tsa[cntB[B[i]] --] = i; for (int i=n; i; --i) sa[cntA[A[tsa[i]]] --] = tsa[i]; rank[sa[1]] = 1; for (int i=2; i<=n; ++i) { rank[sa[i]] = rank[sa[i-1]]; if(A[sa[i]] != A[sa[i-1]] || B[sa[i]] != B[sa[i-1]]) ++rank[sa[i]]; } } } inline void getheight() { for (int i=1, j=0; i<=n; ++i) { if(j) --j; while(ch[i+j] == ch[sa[rank[i]-1] + j]) ++j; h[rank[i]] = j; } } int main() { scanf("%s", ch+1); n = strlen(ch+1); int c = n; ch[n+1] = '$'; scanf("%s", ch+n+2); n = strlen(ch+1); // printf("%s\n", ch+1); getsa(); getheight(); for (int i=2; i<=n; ++i) { int pre, suf; pre = sa[i-1], suf = sa[i]; if(pre > suf) swap(pre, suf); if(pre <= c && suf > c) ans = max(ans, h[i]); } cout << ans; return 0; }