字符串 Alex_Wei
BrotherCall · · 个人记录
Manacher
模板:
#include <bits/stdc++.h>
using namespace std;
const int N = 2.2e7 + 5;
int n, m, ans, R[N];
char s[N], t[N];
int main() {
scanf("%s", s + 1), n = strlen(s + 1);
t[0] = '!', t[m = 1] = '@';
for(int i = 1; i <= n; i++) t[++m] = s[i], t[++m] = '@';
t[++m] = '#';
for(int i = 1, c = 0, r = 0; i < m; i++) {
R[i] = r < i ? 0 : min(R[c * 2 - i], r - i + 1);
while(t[i - R[i]] == t[i + R[i]]) R[i]++;
ans = max(ans, R[i] - 1);
if(i + R[i] - 1 > r) c = i, r = i + R[i] - 1;
}
cout << ans << endl;
return 0;
}
改编自 Alex_Wei,主要是把回文半径的初始值从
题目都做了一遍,评价为目前没有难点。
扩展 KMP
scanf("%s" , c1 + 1);
scanf("%s" , c2 + 1);
int len1 = strlen(c1 + 1) , len2 = strlen(c2 + 1);
z[1] = len2;
for(int i = 2 , l = 0 , r = 0;i <= len2;i ++) {
z[i] = i > r ? 0 : min(z[i - l + 1] , r - i + 1);
while(c2[1 + z[i]] == c2[i + z[i]]) z[i] ++;
if(i + z[i] - 1 > r) {
l = i , r = i + z[i]- 1;
}
}
for(int i = 1 , l = 0 , r = 0;i <= len1;i ++) {
p[i] = i > r ? 0 : min(z[i - l + 1] , r - i + 1);
while(p[i] < len2 && c2[1 + p[i]] == c1[i + p[i]]) p[i] ++;
if(i + p[i] - 1 > r) {
l = i , r = i + p[i] - 1;
}
}
扩展 KMP 简述:和 Manacher 原理很像,不断扩充右端点,用已知信息扩充得到该点信息。
用途:得到文本串以
CF526D
相当漂亮的题。
首先题目非常抽象,
首先说一下直观的 Alex_Wei 的做法,就是既然是一个
若是,还要看后面多少是
另外一个不用扩
我们需要把
如果
否则说明最后多了点循环节的前缀,那需要满足