1 条题解
-
0
预处理阶段
-
后缀自动机(SAM)构建:
其中 是模式串 的长度。
-
文本串 匹配:
其中 是文本串 的长度。
-
稀疏表(ST表)预处理:
其中 是文本串 的长度。
查询阶段
-
每组查询的二分时间复杂度:
其中 是文本串 的长度。
-
单次区间最大值查询:
整体时间复杂度
其中 是模式串 的长度, 是文本串 的长度, 是查询次数。
关键验证逻辑
对于二分答案中的长度 ,验证条件为: 存在 使得 ,其中 表示 中以第 个字符结尾的子串与 的最长公共子串长度。
算法步骤
- 构建 的 SAM:线性时间
- 匹配 得到 数组:线性时间
- 预处理 的 ST 表:
- 处理每组查询:
- 二分答案:
- 每次验证:(ST 表区间最大值查询)
这种组合解法充分利用了各算法的优势,确保在大数据范围下的高效运行。
AC code:
#include <bits/stdc++.h> using namespace std; const int MAXN = 2e5 + 5; const int MAX_SAM = 4e5 + 5; struct SAMNode { int len, link; int next[2]; SAMNode() { len = 0; link = -1; memset(next, -1, sizeof(next)); } } sam[MAX_SAM]; int sam_cnt, last; void sam_init() { sam_cnt = 0; last = 0; sam[0] = SAMNode(); } void sam_extend(int c) { int cur = ++sam_cnt; sam[cur].len = sam[last].len + 1; int p = last; while (p != -1 && sam[p].next[c] == -1) { sam[p].next[c] = cur; p = sam[p].link; } if (p == -1) { sam[cur].link = 0; } else { int q = sam[p].next[c]; if (sam[p].len + 1 == sam[q].len) { sam[cur].link = q; } else { int clone = ++sam_cnt; sam[clone].len = sam[p].len + 1; memcpy(sam[clone].next, sam[q].next, sizeof(sam[q].next)); sam[clone].link = sam[q].link; while (p != -1 && sam[p].next[c] == q) { sam[p].next[c] = clone; p = sam[p].link; } sam[q].link = clone; sam[cur].link = clone; } } last = cur; } int log_table[MAXN]; int dp[MAXN][20]; int len_S[MAXN]; int n, m, q; void st_preprocess() { log_table[1] = 0; for (int i = 2; i <= n; i++) { log_table[i] = log_table[i / 2] + 1; } int k_max = log_table[n] + 1; for (int i = 1; i <= n; i++) { dp[i][0] = len_S[i]; } for (int j = 1; j < k_max; j++) { for (int i = 1; i + (1 << j) - 1 <= n; i++) { dp[i][j] = max(dp[i][j-1], dp[i + (1 << (j-1))][j-1]); } } } int st_query(int l, int r) { if (l > r) return 0; int k = log_table[r - l + 1]; return max(dp[l][k], dp[r - (1 << k) + 1][k]); } int main() { freopen("seal.in", "r", stdin); freopen("seal.out", "w", stdout); ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin >> n >> m >> q; string S, T; cin >> S >> T; S = " " + S; T = " " + T; sam_init(); for (int i = 1; i <= m; i++) { sam_extend(T[i] - '0'); } int cur = 0, cnt = 0; for (int i = 1; i <= n; i++) { int c = S[i] - '0'; while (cur != -1 && sam[cur].next[c] == -1) { cur = sam[cur].link; if (cur != -1) cnt = sam[cur].len; else cnt = 0; } if (cur == -1) { cur = 0; cnt = 0; } else { cur = sam[cur].next[c]; cnt++; } len_S[i] = cnt; } st_preprocess(); while (q--) { int l, r; cin >> l >> r; int max_L = min(r - l + 1, m); int low = 0, high = max_L, ans = 0; while (low <= high) { int mid = (low + high) / 2; if (mid == 0) { ans = mid; low = mid + 1; continue; } int Lk = l + mid - 1; int Rk = r; if (Lk > Rk) { high = mid - 1; continue; } int max_val = st_query(Lk, Rk); if (max_val >= mid) { ans = mid; low = mid + 1; } else { high = mid - 1; } } cout << ans << endl; } return 0; } -
- 1
信息
- ID
- 200
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 8
- 标签
- 递交数
- 6
- 已通过
- 3
- 上传者