#include<bits/stdc++.h> #define STC static usingnamespace std; constint N = 1e6 + 5; int n; char s[N]; int sa[N], rk[N], hei[N]; voidget_sa(int _num) { STC int x[N], y[N], c[N]; //排序用,第一关键字,第二关键字,cnt for (int i = 1; i <= n; ++i) ++c[x[i] = s[i]]; //第一次只有一个字符,不必离散化 for (int i = 2; i <= _num; ++i) c[i] += c[i - 1]; for (int i = n; i >= 1; --i) sa[c[x[i]]--] = i; for (int k = 1, num; k <= n; k <<= 1) //k枚举关键字长度,合并后长度应为2k { num = 0; //记录离散化后的值域 //先以第二关键字排序 for (int i = n - k + 1; i <= n; ++i) //没有第二关键字的牌最前 y[++num] = i; for (int i = 1; i <= n; ++i) if (sa[i] > k) y[++num] = sa[i] - k; //以第一关键字排序 for (int i = 1; i <= _num; ++i) c[i] = 0; for (int i = 1; i <= n; ++i) ++c[x[i]]; for (int i = 2; i <= _num; ++i) c[i] += c[i - 1]; for (int i = n; i >= 1; --i) sa[c[x[y[i]]]--] = y[i], y[i] = 0; //这里清空y实际上是清空x,因为后面交换了 swap(x, y); //将排好序的字符串离散化 x[sa[1]] = num = 1; for (int i = 2; i <= n; ++i) x[sa[i]] = (y[sa[i]] == y[sa[i - 1]] && y[sa[i] + k] == y[sa[i - 1] + k]) ? num : ++num; if (num == n) break; _num = num; } for (int i = 1; i <= n; ++i) rk[sa[i]] = i; } voidget_hei() { int k = 0; for (int i = 1; i <= n; ++i) { if (rk[i] == 1) continue; if (k) --k; int j = sa[rk[i] - 1]; while (i + k <= n && j + k <= n && s[i + k] == s[j + k]) ++k; hei[rk[i]] = k; } } intmain() { scanf("%s", s + 1); n = strlen(s + 1); get_sa('z'); get_hei(); for (int i = 1; i <= n; ++i) printf("%d ", sa[i]); putchar('\n'); for (int i = 1; i <= n; ++i) printf("%d ", hei[i]); return0; }
#include<bits/stdc++.h> #define STC static usingnamespace std; constint N = 3e6 + 5, D = 30; //开大点 int n; char T[N], P[N], s[N]; int sa[N], rk[N], hei[N]; structST { int mn[N][D]; int log_2[N]; voidprev(int x[]) { log_2[1] = 0; for (int i = 2; i <= n; ++i) log_2[i] = log_2[i >> 1] + 1; for (int i = 1; i <= n; ++i) mn[i][0] = x[i]; for (int j = 1; j <= log_2[n] + 1; ++j) for (int i = 1; i <= n - (1 << j) + 1; ++i) mn[i][j] = min(mn[i][j - 1], mn[i + (1 << (j - 1))][j - 1]); } intask(int l, int r) { int t = log_2[r - l + 1]; returnmin(mn[l][t], mn[r - (1 << t) + 1][t]); } } st; voidget_sa(int _num) { STC int x[N], y[N], c[N]; for (int i = 1; i <= n; ++i) ++c[x[i] = T[i]]; for (int i = 2; i <= _num; ++i) c[i] += c[i - 1]; for (int i = n; i >= 1; --i) sa[c[x[i]]--] = i; for (int k = 1, num; k <= n; k <<= 1) { num = 0; for (int i = n - k + 1; i <= n; ++i) y[++num] = i; for (int i = 1; i <= n; ++i) if (sa[i] > k) y[++num] = sa[i] - k; for (int i = 1; i <= _num; ++i) c[i] = 0; for (int i = 1; i <= n; ++i) ++c[x[i]]; for (int i = 2; i <= _num; ++i) c[i] += c[i - 1]; for (int i = n; i >= 1; --i) sa[c[x[y[i]]]--] = y[i], y[i] = 0; swap(x, y); x[sa[1]] = num = 1; for (int i = 2; i <= n; ++i) x[sa[i]] = (y[sa[i]] == y[sa[i - 1]] && y[sa[i] + k] == y[sa[i - 1] + k]) ? num : ++num; if (num == n) break; _num = num; } for (int i = 1; i <= n; ++i) rk[sa[i]] = i; } voidget_hei() { int k = 0; for (int i = 1; i <= n; ++i) { if (rk[i] == 1) continue; if (k) --k; int j = sa[rk[i] - 1]; while (i + k <= n && j + k <= n && T[i + k] == T[j + k]) ++k; hei[rk[i]] = k; } } intlcp(int x, int y) { if (x == y) return n - sa[x] + 1; if (x > y) swap(x, y); return st.ask(x + 1, y); } char* suf(int x) { return T + x - 1; //减1是为了让下标从1开始 } intfind(char *x) { int l = 2, r = n, m = strlen(x + 1); int pos = 1, mxl = 0; //pos初值不能为0,否则ST表会RE char *t = suf(sa[1]); while (mxl < m) { if (sa[1] + mxl > n || t[mxl + 1] != x[mxl + 1]) //为防止越界 break; ++mxl; } if (mxl == m) return pos; while (l <= r) { int mid = l + r >> 1; int len = lcp(mid, pos); t = suf(sa[mid]); //这里一定是sa[mid]不是mid if (len >= mxl) { len = mxl; pos = mid; while (len < m) { if (sa[mid] + len > n || t[len + 1] != x[len + 1]) //为防止越界 break; ++len; } } if (len == m) return pos; elseif (sa[mid] + len > n || x[len + 1] > t[len + 1]) l = mid + 1; else r = mid - 1; } return-1; } intmain() {
int q, ans = 0; scanf("%d", &q); for (int i = 1, cs = 0; i <= q; ++i) { char ch = getchar(); while (ch < 'a' || ch > 'z') ch = getchar(); while (ch >= 'a' && ch <= 'z') s[++cs] = ch, ch = getchar(); s[++cs] = '$'; } scanf("%s", T + 1); n = strlen(T + 1); get_sa('z'); get_hei(); st.prev(hei); for (int i = 1, cs = 1, j; i <= q; ++i) { for (j = 1; s[cs] != '$'; ++cs, ++j) P[j] = s[cs]; ++cs; P[j] = 0; if (find(P) != -1) ++ans; } printf("%d\n", ans); return0; }
#include<bits/stdc++.h> constint N = 2e4 + 100; int n, num, s[N], ans = 0; namespace SA { constint D = 16; int sa[N], rk[N], hei[N], mn[N][D], lg2[N], len; int x[N], y[N], c[N]; template<typename T> voidget_sa(T s[], int _len, int mxv) { len = _len; int i, k, nxv; for (i = 1; i <= len; ++i) ++c[x[i] = s[i]]; for (i = 2; i <= mxv; ++i) c[i] += c[i - 1]; for (i = len; i; --i) sa[c[x[i]]--] = i; for (k = 1; k <= len; k <<= 1) { for (nxv = 0, i = len - k + 1; i <= len; ++i) y[++nxv] = i; for (i = 1; i <= len; ++i) if (sa[i] > k) y[++nxv] = sa[i] - k; memset(c + 1, 0, mxv << 2); for (i = 1; i <= len; ++i) ++c[x[i]]; for (i = 2; i <= mxv; ++i) c[i] += c[i - 1]; for (i = len; i; --i) sa[c[x[y[i]]]--] = y[i], y[i] = 0; std::swap(x, y); x[sa[1]] = nxv = 1; for (i = 2; i <= len; ++i) x[sa[i]] = y[sa[i]] == y[sa[i - 1]] && y[sa[i] + k] == y[sa[i - 1] + k] ? nxv : ++nxv; if (nxv == len) break; mxv = nxv; } for (int i = 1; i <= len; ++i) rk[sa[i]] = i; } template<typename T> voidget_hei(T s[]) { for (int i = 1, j, k = 0; i <= n; ++i) { if (rk[i] == 1) continue; if (k) --k; j = sa[rk[i] - 1]; while (i + k <= len && j + k <= len && s[i + k] == s[j + k]) ++k; hei[rk[i]] = k; } } voidprev() { lg2[1] = 0; for (int i = 2; i <= len; ++i) lg2[i] = lg2[i >> 1] + 1; for (int i = 1; i <= len; ++i) mn[i][0] = hei[i]; for (int j = 1, t = lg2[len]; j <= t; ++j) for (int i = 1; i <= len - (1 << j) + 1; ++i) mn[i][j] = std::min(mn[i][j - 1], mn[i + (1 << (j - 1))][j - 1]); } intlcp(int i, int j) { if (i == j) return len - sa[i] + 1; if (i > j) std::swap(i, j); ++i; int t = lg2[j - i + 1]; return std::min(mn[i][t], mn[j - (1 << t) + 1][t]); } } usingnamespace SA; intmain() { scanf("%d %d", &n, &num); int mx = 0; for (int i = 1; i <= n; ++i) scanf("%d", &s[i]), mx = std::max(s[i], mx); get_sa(s, n, mx), get_hei(s), prev(); for (int i = 1; i + num - 1 <= n; ++i) ans = std::max(ans, lcp(i, i + num - 1)); printf("%d\n", ans); return0; }