题解:P13867 [SWERC 2020] Unique Activities
Exscallop64_ · · 题解
题目简述
给定一个字符串
思路
令
首先注意到一个性质,如果存在合法的长度为
那么,我们就可以二分答案 map 判断。
时间复杂度
-
时间复杂度:二分答案
O(\log n) ,如果使用unordered_map并假设为O(1) 不计复杂度,则判断部分为O(n) ,总复杂度O(n \log n) 。 -
空间复杂度:
O(n) 。
#include<bits/stdc++.h>
using namespace std;
using pii = pair<int, int>;
using ll = long long;
const int MAXN = 3e5 + 5, BASE = 64007;
const ll MOD = 2999999929;
int n;
ll power[MAXN], h[MAXN];
string s;
unordered_map<ll, int> cnt;
int Query(int l, int r){
return (h[r] - h[l - 1] * power[r - l + 1] % MOD + MOD) % MOD;
}
int Check(int len){
cnt.clear();
for(int i = 1; i <= n - len + 1; i++){
cnt[Query(i, i + len - 1)]++;
}
for(int i = 1; i <= n - len + 1; i++){
if(cnt[Query(i, i + len - 1)] == 1) return i;
}
return 0;
}
int main(){
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> s;
n = s.size(), s = "#" + s;
power[0] = 1;
for(int i = 1; i <= n; i++){
power[i] = power[i - 1] * BASE % MOD;
h[i] = (h[i - 1] * BASE % MOD + s[i] - 'A') % MOD;
}
int l = 0, r = n;
while(l < r){
int mid = (l + r) >> 1;
Check(mid) ? r = mid : l = mid + 1;
}
cout << s.substr(Check(l), l);
return 0;
}
后记
给一些字符串哈希的小技巧吧,适合一些哈希新手。
虽然这题不卡哈希,但是不难想到 CF 特别喜欢拐卖
当然你可以使用双哈希,但是码量翻倍,当你懒的再找质数是个好办法。
也可以赛前积累一些怪异质数,比如
不过我经常临场找,我们知道
#include<bits/stdc++.h>
using namespace std;
int n;
bool Check(int n){
if(n <= 2) return n == 2;
for(int i = 2; i * i <= n; i++){
if(n % i == 0) return 0;
}
return 1;
}
int main(){
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n;
while(!Check(n)) n++;
cout << n;
return 0;
}