http://acm.hdu.edu.cn/showproblem.php?pid=5558
对于每个后缀suffix(i),想要在前面i - 1个suffix中找到一个pos,使得LCP最大。这样做O(n^2)
考虑到对于每一个suffix(i),最长的LCP肯定在和他排名相近的地方取得。
按排名大小顺序枚举位置,按位置维护一个递增的单调栈,对于每一个进栈的元素,要算一算栈内元素和他的LCP最大是多少。
如果不需要输出最小的下标,最大的直接是LCP(suffix(st[top]), suffix(st[top - 1]))就是相邻的两个。
但是要求最小的下标,这样的话需要对整个栈进行一个遍历,找到下标最小的并且长度最大的。整个栈与新进来的栈顶元素的LCP存在单调性,单调递增,所以可以二分。
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <vector> #include <queue> #include <string> #include <stack> #include <map> #include <set> #include <bitset> #define X first #define Y second #define clr(u,v); memset(u,v,sizeof(u)); #define in() freopen("data.txt","r",stdin); #define out() freopen("ans","w",stdout); #define Clear(Q); while (!Q.empty()) Q.pop(); #define pb push_back #define inf (0x3f3f3f3f) using namespace std; typedef long long ll; typedef pair<int, int> pii; const int INF = 0x3f3f3f3f; const int maxn = 100000 + 2; int sa[maxn], x[maxn], y[maxn], book[maxn]; bool cmp(int r[], int a, int b, int len) { return r[a] == r[b] && r[a + len] == r[b + len]; } void da(char str[], int sa[], int lenstr, int mx) { int *fir = x, *sec = y, *ToChange; for (int i = 0; i <= mx; ++i) book[i] = 0; for (int i = 1; i <= lenstr; ++i) { fir[i] = str[i]; book[str[i]]++; } for (int i = 1; i <= mx; ++i) book[i] += book[i - 1]; for (int i = lenstr; i >= 1; --i) sa[book[fir[i]]--] = i; for (int j = 1, p = 1; p <= lenstr; j <<= 1, mx = p) { p = 0; for (int i = lenstr - j + 1; i <= lenstr; ++i) sec[++p] = i; for (int i = 1; i <= lenstr; ++i) { if (sa[i] > j) sec[++p] = sa[i] - j; } for (int i = 0; i <= mx; ++i) book[i] = 0; for (int i = 1; i <= lenstr; ++i) book[fir[sec[i]]]++; for (int i = 1; i <= mx; ++i) book[i] += book[i - 1]; for (int i = lenstr; i >= 1; --i) sa[book[fir[sec[i]]]--] = sec[i]; // ToChange = fir, fir = sec, sec = ToChange; swap(fir, sec); fir[sa[1]] = 0; p = 2; for (int i = 2; i <= lenstr; ++i) { fir[sa[i]] = cmp(sec, sa[i - 1], sa[i], j) ? p - 1 : p++; } } } int height[maxn], RANK[maxn]; void calcHight(char str[], int sa[], int lenstr) { for (int i = 1; i <= lenstr; ++i) RANK[sa[i]] = i; int k = 0; for (int i = 1; i <= lenstr - 1; ++i) { k -= k > 0; int j = sa[RANK[i] - 1]; while (str[j + k] == str[i + k]) ++k; height[RANK[i]] = k; } } char str[maxn]; int dp[maxn][19]; vector<int> fuck[26]; const int need = 18; void init_RMQ(int n, int a[]) { for (int i = 1; i <= n; ++i) { dp[i][0] = a[i]; } for (int j = 1; j < need; ++j) { for (int i = 1; i + (1 << j) - 1 <= n; ++i) { dp[i][j] = min(dp[i][j - 1], dp[i + (1 << (j - 1))][j - 1]); } } } int ask(int be, int en) { if (be > en) swap(be, en); be++; int k = (int)log2(en - be + 1); return min(dp[be][k], dp[en - (1 << k) + 1][k]); } int f; int st[maxn], top; int t[maxn]; int ans[maxn], id[maxn]; bool check(int pos, int len) { int res = ask(RANK[st[pos]], RANK[st[top]]); return res == len; } void work() { memset(ans, 0, sizeof ans); memset(id, 0x3f, sizeof id); scanf("%s", str + 1); int lenstr = strlen(str + 1); str[lenstr + 1] = '$'; str[lenstr + 2] = '