洛谷 P7114 / LOJ 3387 「NOIP2020」字符串匹配
思路
令 。首先求出 的 函数数组 ,考虑将 视作一个整体的循环节,那么长度为 的循环节最多可以接上 组。
这个理解起来很简单。根据定义,子串 与 相同,即 与 相同, 与 ,相同,以此类推。
然后考虑题中 的限制。枚举 的长度,记 为 中出现次数为奇数的字符数量。令循环节出现次数为 ,发现只用考虑 为奇数或偶数的情况,因为 与 的字符出现次数的奇偶情况相同。设 ,当 为奇数,则 可行当且仅当 ;当 为偶数,则 可行当且仅当 。用树状数组维护当前所有前缀 中出现次数为奇数的字符数量为 的前缀个数。易知 为奇数时有 种情况,为偶数时有 种情况,乘法原理计算即可。
时间复杂度 。实现细节见代码。
代码
code
/* p_b_p_b txdy AThousandMoon txdy AThousandSuns txdy hxy txdy */ #include <bits/stdc++.h> #define pb push_back #define fst first #define scd second using namespace std; typedef long long ll; typedef pair<ll, ll> pii; const int maxn = 1050000; int n, nxt[maxn], c[30], cnt1[30], cnt2[30]; char s[maxn]; int lowbit(int x) { return x & (-x); } void update(int x, int d) { for (int i = x; i <= 27; i += lowbit(i)) { c[i] += d; } } int query(int x) { int res = 0; for (int i = x; i; i -= lowbit(i)) { res += c[i]; } return res; } void solve() { memset(c, 0, sizeof(c)); memset(cnt1, 0, sizeof(cnt1)); memset(cnt2, 0, sizeof(cnt2)); scanf("%s", s + 1); n = strlen(s + 1); // 求 Z 函数 nxt[1] = n; for (int i = 2, l = 0, r = 0; i <= n; ++i) { nxt[i] = (i > r) ? 0 : min(nxt[i - l + 1], r - i + 1); while (s[nxt[i] + 1] == s[nxt[i] + i]) { ++nxt[i]; } if (i + nxt[i] - 1 > r) { l = i; r = i + nxt[i] - 1; } } // 由于 C 非空,所以空一个位置给 C for (int i = 1; i <= n; ++i) { if (i + nxt[i] - 1 == n) { --nxt[i]; } } for (int i = 1; i <= n; ++i) { ++cnt2[s[i] - 'a']; } // 维护当前前缀和后缀中出现次数为奇数的字符个数 int pre = 0, suf = 0; for (int i = 0; i < 26; ++i) { if (cnt2[i] & 1) { ++suf; } } int sum = suf; ll ans = 0; for (int i = 1; i < n; ++i) { if (cnt1[s[i] - 'a'] & 1) { --pre; } else { ++pre; } ++cnt1[s[i] - 'a']; if (cnt2[s[i] - 'a'] & 1) { --suf; } else { ++suf; } --cnt2[s[i] - 'a']; // A,B 非空,因此空至少一个位置给 B if (i > 1) { ll x = nxt[i + 1] / i + 1; ans += (x - x / 2) * query(suf + 1) + (x / 2) * query(sum + 1); } update(pre + 1, 1); // 因为下表可能为 0,所以树状数组下标整体加一 } printf("%lld\n", ans); } int main() { int T = 1; scanf("%d", &T); while (T--) { solve(); } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】