题面:给一个长度为2n的字符串T,问是否存在长度为n的字符串S,满足:T = S的前缀 + 整串S逆序 + S的后缀。
范围:n<=1e6
思路:字符串哈希,枚举S的起点逐一判断,如果前i个字符加后n-i个字符组成的长为n的字符串,正好和中间串的逆序相同,则为解。
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define rep(i,a,b) for(int i=a; i<=b; i++)
#define per(i,a,b) for(int i=b; i>=a; i--)
using hval = tuple<int,int,int>;
struct Hasher {
const int B1 = 131, M1 = 1000000123;
const int B2 = 137, M2 = 1000000223;
const int B3 = 139, M3 = 1000000007;
vector<int> P1, P2, P3, L1, L2, L3;
template<typename InputIt>
void init(InputIt st, InputIt ed) {
int n = distance(st, ed);
P1 = P2 = P3 = vector<int>(n+5, 1);
rep(i,1,n) {
P1[i] = P1[i-1] * B1 % M1;
P2[i] = P2[i-1] * B2 % M2;
P3[i] = P3[i-1] * B3 % M3;
}
L1 = L2 = L3 = vector<int>(n+5, 0);
rep(i,1,n) {
L1[i] = (L1[i-1] * B1 + st[i-1]) % M1;
L2[i] = (L2[i-1] * B2 + st[i-1]) % M2;
L3[i] = (L3[i-1] * B3 + st[i-1]) % M3;
}
}
hval get(initializer_list<int> arg) { // [l1,r1),[l2,r2)..., 0-based
assert(arg.size() % 2 == 0);
int x = 0, y = 0, z = 0;
auto it = arg.begin();
while (it != arg.end()) {
int l = *it++, r = *it++;
x = x * P1[r-l] % M1; x += (L1[r] - L1[l] * P1[r-l]) % M1; if (x < 0) x += M1;
y = y * P2[r-l] % M2; y += (L2[r] - L2[l] * P2[r-l]) % M2; if (y < 0) y += M2;
z = z * P3[r-l] % M3; z += (L3[r] - L3[l] * P3[r-l]) % M3; if (z < 0) z += M3;
}
return {x,y,z};
}
hval get(int l, int r) { return get({l,r}); }
};
void solve() {
int n;
string s;
cin >> n >> s;
Hasher h1, h2;
h1.init(s.begin(), s.end());
h2.init(s.rbegin(), s.rend());
rep(i,0,n) {
if (h1.get({0,i,i+n,2*n}) == h2.get(n-i,2*n-i)) {
string t = s.substr(i,n);
reverse(t.begin(), t.end());
cout << t << "\n" << i;
return;
}
}
cout << -1;
}
signed main() {
cin.tie(0)->sync_with_stdio(0);
int t = 1;
while (t--) solve();
return 0;
}
标签:P2,P3,后缀,int,M1,M3,M2,abc284F,逆序
From: https://www.cnblogs.com/chenfy27/p/18060726