1 条题解
-
0
可以明显看出,瑕疵回文串包含了普通回文串。
首先,我们可以预处理前缀哈希数组 和后缀哈希数组 ,然后结合二分法和前后缀字符串哈希,在 时间复杂度下求得每个下标作为中心时,最长回文串的区间 。
在求出回文串的基础上,我们进一步使用二分法来确定瑕疵字符的长度,使得在区间 处的哈希值与在区间 处的哈希值相等。
最终,答案可以表示为:
在二分过程中需要注意避免越界问题。
时间复杂度:
const int maxn = 2e5 + 7, p = 131; int n; string s; unsigned int hs[maxn], sh[maxn], qy[maxn]; unsigned int get1(int l, int r) { return hs[r] - hs[l - 1] * qy[r - l + 1]; } unsigned int get2(int l, int r) { return sh[l] - sh[r + 1] * qy[r - l + 1]; } bool check(int l1, int r1, int l2, int r2) { if (l2 <= 0 || r1 > n) return false; return get1(l1, r1) == get2(l2, r2); } void solve() { cin >> n >> s; qy[0] = 1; for (int i = 1; i <= n; i++) { qy[i] = qy[i - 1] * p; hs[i] = hs[i - 1] * p + s[i - 1] - 'a'; } for (int i = n; i >= 1; i--) sh[i] = sh[i + 1] * p + s[i - 1] - 'a'; int ans = 0; for (int i = 1; i <= n; i++) { int l = 0, r = n; while (l < r) { int mid = (l + r + 1) / 2; if (check(i, i + mid, i - mid, i)) l = mid; else r = mid - 1; } int tmp = l; if (i + (tmp + 1) <= n && i - (tmp + 1) > 0) tmp++; l = 0, r = n; while (l < r) { int mid = (l + r + 1) / 2; if (check(i + tmp + 1, i + tmp + mid, i - tmp - mid, i - tmp - 1)) l = mid; else r = mid - 1; } ans = max(ans, 1 + (tmp + l) * 2); } for (int i = 1; i < n; i++) { int l = 0, r = n; while (l < r) { int mid = (l + r + 1) / 2; if (check(i + 1, i + mid, i + 1 - mid, i)) l = mid; else r = mid - 1; } int tmp = l; if (i + (tmp + 1) <= n && i + 1 - (tmp + 1) > 0) tmp++; l = 0, r = n; while (l < r) { int mid = (l + r + 1) / 2; if (check(i + tmp + 1, i + tmp + mid, i + 1 - tmp - mid, i - tmp)) l = mid; else r = mid - 1; } ans = max(ans, (tmp + l) * 2); } cout << ans << endl; }
- 1
信息
- ID
- 5
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者