题解:Testing Round 19 (Div. 3) C2(KMP/字符串哈希)
题意
给你一个字符串,问:
这个字符串有没有可能是两个相同的字符串部分重合首尾拼接在一起的
如果是,输出YES
,并输出任意一种字符串
如果不是,则输出NO
题解1
首先计算以这个字符串为模板的(KMP的)\(next\) 数组
假如最后一个字符的 \(next\) 值大于原字符串长度的 \(\frac{1}{2}\)
答案则为是,输出从第一个字符 到 字符串的 最后一个字符的 \(next\) 值 的位置
否则,答案则为否
代码
#include <bits/stdc++.h>
#define all(x) x.begin(),x.end()
#define INF 0x3f3f3f3f
#define int long long
using i64 = long long;
int t = 1;
void solve() {
std::string s;
std::cin >> s;
int l = s.size();
std::vector<int> f(l + 1 , 0);
for (int i = 1, j = 0; i < l; i++) {
while (j > 0 && s[i] != s[j]) {
j = f[j];
}
j += (s[i] == s[j]);
f[i + 1] = j;
}
if (f[l] > l/2) {
std::cout << "YES\n";
for(int i = 0 ; i < f[l] ; i ++) std::cout << s[i];
} else {
std::cout << "NO\n";
}
}
signed main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
//std::cin >> t;
while(t--) solve();
return 0;
}
题解2
字符串哈希:
从中间的字符开始,截取第一个字符到这个字符的字符串,和相同长度的末尾的字符串,进行字符串哈希。
如果哈希值相同,则是,并输出该字符串
如果哈希值不同,则否
代码2
from Jayket
#include<bits/stdc++.h>
using u32 = uint32_t;
using i64 = int64_t;
using u64 = uint64_t;
using f64 = long double;
using i128 = __int128;
using f128 = __float128;
#ifndef ONLINE_JUDGE
#include "algo\debug.hpp"
#else
#define debug(...) (void)42
#endif
template<class T>
void chmax(T& x, T y) {
x = std::max(x, y);
}
template<class T>
void chmin(T& x, T y) {
x = std::min(x, y);
}
std::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());
int rand(int l, int r) {
return std::uniform_int_distribution<int>(l, r)(rng);
}
static constexpr int Ub = 6;
static constexpr int MODPOOL[] = {741828491, 906403529, 1009420513, 1344508289, 1593699529, 1745165407, 1951360013};
static constexpr int BASEPOOL[] = {37, 53, 73, 77, 89, 91, 97};
int MOD1, MOD2, BASE1, BASE2;
constexpr int M = 1E6;
int p1[M + 1], p2[M + 1];
struct Hash {
std::vector<int>h1, h2;
Hash() {}
Hash(const std::string& s) {
int n = s.size();
h1.resize(n + 1);
h2.resize(n + 1);
for (int i = 1; i <= n; i += 1) {
h1[i] = (1LL * h1[i - 1] * BASE1 % MOD1 + s[i - 1]) % MOD1;
h2[i] = (1LL * h2[i - 1] * BASE2 % MOD2 + s[i - 1]) % MOD2;
}
}
std::pair<int, int> getRange(int l, int r) {
int a = (1LL * h1[r] - 1LL * h1[l - 1] * p1[r - l + 1] % MOD1 + MOD1) % MOD1;
int b = (1LL * h2[r] - 1LL * h2[l - 1] * p2[r - l + 1] % MOD2 + MOD2) % MOD2;
return std::pair(a, b);
}
};
void init(int n) {
MOD1 = MOD2 = MODPOOL[3];
BASE1 = BASE2 = BASEPOOL[3];
while (MOD1 == MOD2) {
int x = rand(0, Ub), y = rand(0, Ub);
MOD1 = MODPOOL[x];
MOD2 = MODPOOL[y];
}
while (BASE1 == BASE2) {
int x = rand(0, Ub), y = rand(0, Ub);
BASE1 = BASEPOOL[x];
BASE2 = BASEPOOL[y];
}
p1[0] = p2[0] = 1;
for (int i = 1; i <= n; i += 1) {
p1[i] = 1LL * p1[i - 1] * BASE1 % MOD1;
p2[i] = 1LL * p2[i - 1] * BASE2 % MOD2;
}
}
auto main() ->int32_t {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout << std::fixed << std::setprecision(13);
init(M);
std::string s;
std::cin >> s;
Hash qs(s);
int n = s.size();
for (int i = n / 2 + 1; i <= n - 1; i += 1) {
if (qs.getRange(1, i) == qs.getRange(n - i + 1, n)) {
std::cout << "YES\n";
std::cout << s.substr(0, i) << '\n';
return 0;
}
}
std::cout << "NO\n";
return 0;
}
posted on 2024-09-01 23:58 Jiejiejiang 阅读(58) 评论(0) 编辑 收藏 举报