思路
刚开始我是写的暴力+倍增排序,全盘 WA 掉之后怀疑人生。然后看正解,二分果然很毒瘤。
先准备数据,写好字符串哈希。读者如果不清楚如何求字符串哈希的话就来看着篇文章:字符串哈希例题
然后,我们考虑针对\(sort\)函数写一个比较函数。我们可以选择在区间\([0,min\{len-a+1,len-b+1\}]\)中二分出一个相等前缀长度,那么\(check(mid)\)函数就很好写了,直接判断两者的哈希值是否相等即可。
代码
// CH1402.cpp #include <iostream> #include <algorithm> #define ull long long using namespace std; const int maxn = 300000 + 1000; string str = ""; int idxs[maxn], siz; ull hashtable[maxn], power[maxn], bitNum = 133; bool cmp(int a, int b) { int range = min(str.length() - a + 1, str.length() - b + 1); int l = 0, r = range, pl = 0; while (l <= r) { int mid = (l + r) >> 1; if (hashtable[a + mid - 1] - hashtable[a - 1] * power[mid] == hashtable[b + mid - 1] - hashtable[b - 1] * power[mid]) l = mid + 1, pl = mid; else r = mid - 1; } return str[a + pl] < str[b + pl]; } int getLen(int a, int b) { int range = min(str.length() - a + 1, str.length() - b + 1); int l = 0, r = range, pl = 0; while (l <= r) { int mid = (l + r) >> 1; if (hashtable[a + mid - 1] - hashtable[a - 1] * power[mid] == hashtable[b + mid - 1] - hashtable[b - 1] * power[mid]) l = mid + 1, pl = mid; else r = mid - 1; } return pl; } int main() { cin >> str; siz = str.length(); str = ' ' + str, power[0] = 1; for (int i = 1; i <= siz; i++) hashtable[i] = hashtable[i - 1] * bitNum + str[i] - 'a' + 1, power[i] = power[i - 1] * bitNum, idxs[i] = i; sort(idxs + 1, idxs + siz + 1, cmp); for (int i = 1; i <= siz; i++) printf("%d ", idxs[i] - 1); printf("\n0 "); for (int i = 2; i <= siz; i++) printf("%d ", getLen(idxs[i], idxs[i - 1])); return 0; }