OiClass PUJI P2232 Friends 题解

思路

容易发现枚举添加的是哪个字符是很好的,但是我们需要解决哈希的问题。

考虑拼凑,不难发现,对于 ABXC 去掉 X 之后的 AB C 这个字符串,他的哈希是 AB 的哈希乘上 C 的位权。于是我们分类讨论一下删去的字符在哪个位置,然后分别处理即可。

但是在统计答案的时候仍然有很多细节。首先是不能在每次都记录字串,因为取字串的函数复杂度并不优秀。我们需要记录答案的哈希值,然后每次先对比哈希值,如果不同再更新答案。这样在去重的同时可以解决取子串不快的问题。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <iostream>

using namespace std;

int n;
unsigned long long hs[2000009], pw[2000009];
string s;

unsigned long long Hash(int l, int r) {
return hs[r] - hs[l - 1] * pw[r - l + 1];
}

signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
cin >> n >> s;
if ((s.size() & 1) == 0) {
cout << "NOT POSSIBLE";
return 0;
}
pw[0] = 1;
for (int i = 1; i <= n; i++) {
pw[i] = pw[i - 1] * 38734667;
hs[i] = hs[i - 1] * 38734667 + s[i - 1] - 'A';
}
int cnt = 0;
unsigned long long hashs = 1;
string str;
for (int i = 0; i < n; i++) {
unsigned long long h1, h2;
if (i == 0) {
h1 = Hash(2, (n >> 1) + 1), h2 = Hash((n >> 1) + 2, n);
} else if (i > (n >> 1)) {
h1 = Hash(1, (n >> 1)), h2 = Hash((n >> 1) + 1, i) * pw[n - (i + 2) + 1] + Hash(i + 2, n);
} else if (i == (n >> 1)) {
h1 = Hash(1, (n >> 1)), h2 = Hash((n >> 1) + 2, n);
} else {
h1 = Hash(1, i) * pw[(n >> 1) + 1 - (i + 2) + 1] + Hash(i + 2, (n >> 1) + 1), h2 = Hash((n >> 1) + 2, n);
}
if (h1 == h2) {
if (h1 == hashs) {
continue;
}
string s;
if (i == 0) {
s = ::s.substr(1, n >> 1);
} else if (i > (n >> 1)) {
s = ::s.substr(0, n >> 1);
} else if (i == (n >> 1)) {
s = ::s.substr(0, n >> 1);
} else {
s = ::s.substr((n >> 1) + 1, n >> 1);
}
cnt += 1;
hashs = h1;
str = s;
if (cnt > 1) {
cout << "NOT UNIQUE";
return 0;
}
}
}
cout << (cnt > 0 ? str : "NOT POSSIBLE");
}

OiClass PUJI P2232 Friends 题解
https://lixuannan.github.io/posts/31541
作者
CodingCow Lee
发布于
2024年8月7日
许可协议