http://www.lydsy.com/JudgeOnline/problem.php?id=3230
后缀数组
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <queue> #include <algorithm> #include <vector> #include <cstring> #include <stack> #include <cctype> #include <utility> #include <map> #include <string> #include <climits> #include <set> #include <string> #include <sstream> #include <utility> #include <ctime> #include <bitset> #include <iomanip> //#pragma comment(linker, "/STACK:102400000,102400000") using std::priority_queue; using std::vector; using std::swap; using std::stack; using std::sort; using std::max; using std::min; using std::pair; using std::map; using std::string; using std::cin; using std::cout; using std::set; using std::queue; using std::string; using std::stringstream; using std::make_pair; using std::getline; using std::greater; using std::endl; using std::multimap; using std::deque; using std::unique; using std::lower_bound; using std::random_shuffle; using std::bitset; using std::upper_bound; using std::multiset; using std::ios; using std::make_heap; using std::push_heap; using std::pop_heap; typedef long long LL; typedef unsigned long long ULL; typedef unsigned UN; typedef pair<ULL, ULL> PAIR; typedef multimap<int, int> MMAP; typedef long double LF; const int MAXN(100010); const int MAXM(310); const int MAXE(310); const int MAXK(6); const int HSIZE(13131); const int SIGMA_SIZE(26); const int MAXH(18); const int INFI((INT_MAX-1) >> 1); const ULL BASE(31); const LL LIM(1e13); const int INV(-10000); const int MOD(1000000007); const double EPS(1e-7); const LF PI(acos(-1.0)); template<typename T> inline void checkmax(T &a, T b){if(b > a) a = b;} template<typename T> inline void checkmin(T &a, T b){if(b < a) a = b;} template<typename T> inline T ABS(const T &a){return a < 0? -a: a;} int Log[MAXN]; void initLog() { Log[0] = -1; for(int i = 1; i < MAXN; ++i) Log[i] = (i&(i-1))? Log[i-1]: Log[i-1]+1; } struct SA { char S[MAXN]; int sa[MAXN],t1[MAXN], t2[MAXN], cnt[MAXN], len, M; void init(int tl, int tm = 128) { len = tl; M = tm; int *p1 = t1, *p2 = t2; for(int i = 0; i < M; ++i) cnt[i] = 0; for(int i = 0; i <= len; ++i) ++cnt[p1[i] = S[i]]; for(int i = 1; i < M; ++i) cnt[i] += cnt[i-1]; for(int i = len; i >= 0; --i) sa[--cnt[p1[i]]] = i; int temp = 1; for(int k = 1; temp <= len; k <<= 1) { temp = 0; for(int i = len-k+1; i <= len; ++i) p2[temp++] = i; for(int i = 0; i <= len; ++i) if(sa[i] >= k) p2[temp++] = sa[i]-k; for(int i = 0; i < M; ++i) cnt[i] = 0; for(int i = 0; i <= len; ++i) ++cnt[p1[p2[i]]]; for(int i = 1; i < M; ++i) cnt[i] += cnt[i-1]; for(int i = len; i >= 0; --i) sa[--cnt[p1[p2[i]]]] = p2[i]; swap(p1, p2); temp = 1; p1[sa[0]] = 0; for(int i = 1; i <= len; ++i) p1[sa[i]] = p2[sa[i-1]] == p2[sa[i]] && p2[sa[i-1]+k] == p2[sa[i]+k]? temp-1: temp++; M = temp; } } int rank[MAXN], hei[MAXN]; void getHei() { int k = 0; for(int i = 0; i <= len; ++i) rank[sa[i]] = i; for(int i = 0; i < len; ++i) { if(k) --k; int j = sa[rank[i]-1]; while(S[i+k] == S[j+k]) ++k; hei[rank[i]] = k; } } int dp[MAXH][MAXN]; void initRMQ() { for(int i = 1; i <= len; ++i) dp[0][i] = hei[i]; for(int i = 1; (1 << i) <= len; ++i) for(int j = 1; j+(1 << i)-1 <= len; ++j) dp[i][j] = min(dp[i-1][j], dp[i-1][j+(1 << (i-1))]); } int lcp(int a, int b) { if(a == b) return len-a; a = rank[a]; b = rank[b]; if(a > b) swap(a, b); ++a; int temp = Log[b-a+1]; return min(dp[temp][a], dp[temp][b-(1 << temp)+1]); } } sa1, sa2; LL rec[MAXN]; int main() { initLog(); int n, Q; scanf("%d%d", &n, &Q); scanf("%s", sa1.S); for(int i = 0; i < n; ++i) sa2.S[i] = sa1.S[n-i-1]; sa2.S[n] = '\0'; sa1.init(n); sa2.init(n); sa1.getHei(); sa2.getHei(); sa1.initRMQ(); sa2.initRMQ(); for(int i = 1; i <= n; ++i) rec[i] = rec[i-1]+(n-sa1.sa[i]-sa1.hei[i]); LL q1, q2; for(int i = 0; i < Q; ++i) { scanf("%lld%lld", &q1, &q2); int i1 = lower_bound(rec, rec+1+n, q1)-rec; int i2 = lower_bound(rec, rec+1+n, q2)-rec; if(i1 > n || i2 > n) { printf("-1\n"); continue; } int l1 = (n-sa1.sa[i1])-(rec[i1]-q1); int l2 = (n-sa1.sa[i2])-(rec[i2]-q2); LL a = min(sa1.lcp(sa1.sa[i1], sa1.sa[i2]), min(l1, l2)); LL b = min(sa2.lcp(n-1-(sa1.sa[i1]+l1-1), n-1-(sa1.sa[i2]+l2-1)), min(l1, l2)); printf("%lld\n", a*a+b*b); } return 0; }