2021ICPC EC final B. Beautiful String题解
今天跟队友vp21年EC final,最后可惜计算几何没开出来,以及J题时间不够没做出来,主要就是B做太麻烦了,导致花了太多时间。但是作为串串人,还是非常喜欢字符串题,这里写一下我们的B题做法。
题意
定义一个好串是能将字符串分为6个部分
分析
最核心的想法如下图所示:
利用S2S3等于S5S6,将两者捆绑起来,就可以用一个类似LCP的东西来求,我们是用的KMP。
具体来说,首先枚举S1的起始位置和长度,就已经
先忽略掉
那么我们去枚举
我的代码里将这部分预处理在了
代码
#include <bits/stdc++.h>
#define int long long
#define ll __int128_t
#define pii pair<int, int>
using namespace std;
const int maxn = 5e3 + 10;
const int mod = 1e18 + 201;
const int base = 131;
int nxt[maxn], Nxt[maxn];
vector<int> G[maxn];
int dp[maxn][maxn], dep[maxn], sub[maxn];
int sufsum[maxn][maxn];
void get_nxt(string& str) {
for (int i = 1, j = 0; i < str.length(); i++) {
while (j && str[i] != str[j])
j = nxt[j - 1];
if (str[i] == str[j])
j++;
nxt[i] = j;
}
}
void get_nxt2(string& str) {
for (int i = 1, j = 0; i < str.length(); i++) {
while (j && str[i] != str[j])
j = nxt[j - 1];
if (str[i] == str[j])
j++;
if (j * 2 >= i + 1)
j = nxt[j - 1];
Nxt[i] = j;
}
}
void dfs2(int u) {
for (auto v : G[u])
dfs2(v), sub[u] += sub[v];
}
struct HASH {
int hash[maxn];
int mi[maxn];
void init(string& str) {
int n = str.length();
mi[0] = 1;
for (int i = 1; i <= n; i++)
mi[i] = (ll)mi[i - 1] * base % mod;
for (int i = 1; i <= n; i++)
hash[i] = ((ll)hash[i - 1] * base + str[i - 1]) % mod;
}
int get_hash(int l, int r) {
return ((ll)hash[r] - (ll)hash[l - 1] * mi[r - l + 1] % mod + mod) %
mod;
}
} Hash;
void solve() {
string str;
cin >> str;
int n = str.length();
for (int i = 1; i <= n; i++) {
int len = n - i + 1;
for (int j = 0; j <= len; j++)
G[j].clear(), sub[j] = 0;
string tem = str.substr(i - 1, len);
get_nxt(tem);
get_nxt2(tem);
for (int j = 1; j <= len; j++)
sub[Nxt[j - 1]]++;
for (int j = 1; j <= len; j++)
G[nxt[j - 1]].push_back(j);
dfs2(0);
for (int j = 1; j <= len; j++)
dp[i][i + j - 1] = sub[j], sufsum[i][i + j - 1] = sub[j];
for (int j = len - 1; j >= 1; j--)
sufsum[i][i + j - 1] += sufsum[i][i + j];
}
Hash.init(str);
int ans = 0;
int debug = 0;
for (int i = 1; i <= n; i++) {
for (int s1len = 1; i + 2 * s1len - 1 <= n; s1len++) {
// s1 [i, i + s1len - 1], s2[i + s1len, i + 2 * s1len - 1]
int l1 = i, r1 = i + s1len - 1;
int l2 = i + s1len, r2 = i + 2 * s1len - 1;
if (Hash.get_hash(l1, r1) != Hash.get_hash(l2, r2))
continue;
if (r2 + 1 > n)
continue;
ans += sufsum[l2][r2 + 1];
}
}
cout << ans << "\n";
}
signed main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t--)
solve();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话