P7114 [NOIP2020] 字符串匹配 解题报告
~~NOIP的蓝题果然还是好难啊啊啊啊~~
前言:
作为一道 NOIP 的真题, 这道题放在 T2 难度并不是特别大,不过考点还是比较偏的,扩展KMP和树状数组的组合,并且还带有一定的思维难度,估计是当年不少人低分的题目,同时也给了一些人翻盘的机会。总而言之, 是道好题。
Description:
将字符串 划分成 的形式,并且满足 中出现奇数次的字符数小于等于 中出现奇数次的字符数。
Solution:
首先发现 中的 是一个循环节,因此想到枚举循环节的长度。
由于 的长度均大于等于1,所以循环节长度应为 。
画个图发现, 对于长度为 的前缀, 它最多循环的次数为 下取整 。设循环次数为 , 表示 中出现奇数次的字符数。 当 为奇数时, , 因此只要找到满足 的 的个数即可, 然后用乘法原理统计。当 为偶数时, 必然等于 , 。
实现可以采用数据结构维护,本题最好用树状数组。
时间复杂度 。
CODE

#include<bits/stdc++.h> using namespace std; #define int long long inline int read() { int x = 0, f = 1; char c = getchar(); while (c < '0' || c > '9') {if (c == '-') f = -f; c = getchar();} while (c >= '0' && c <= '9') {x = (x << 3) + (x << 1) + (c ^ 48); c = getchar();} return x * f; } const int N = (1 << 20) + 10, C = 26; int n; char s[N]; int z[N]; inline void getZ() { z[1] = n; for (int i = 2, l = 0, r = 0; i <= n; ++ i) { if (i <= r) z[i] = min(z[i-l+1], r-i+1); while (i + z[i] <= n && s[i+z[i]] == s[z[i] + 1]) ++ z[i]; if (i + z[i] - 1 > r) r = i + z[i] - 1, l = i; } } int tot[C+10], cnt[C+10], c[C+10]; inline int lowbit (int x) {return x & -x;} inline void add(int x, int v) {for (; x <= C+1; x += lowbit(x)) c[x] += v;} inline int ask (int x) {int res = 0; for (; x > 0; x -= lowbit(x)) res += c[x]; return res;} int ans, all, lst, now; signed main () { int T = read(); while (T --) { scanf("%s", s + 1); n = strlen(s + 1); for (int i = 1; i <= n; ++ i) z[i] = 0; getZ(); for (int i = 1; i <= n; ++ i) if (i + z[i] == n + 1) z[i] --; for (int i = 1; i <= C+1; ++ i) tot[i] = cnt[i] = c[i] = 0; ans = all = lst = now = 0; for (int i = 1; i <= n; ++ i) tot[s[i]-'a'+1] ++; for (int i = 1; i <= C; ++ i) all += (tot[i] & 1); lst = all; for (int i = 1; i <= n; ++ i) { if (tot[s[i]-'a'+1] & 1) lst --; else lst ++; if (cnt[s[i]-'a'+1] & 1) now --; else now ++; tot[s[i]-'a'+1] --; cnt[s[i]-'a'+1] ++; if (i > 1 && i < n) { int t = z[i+1] / i + 1; ans += (t/2) * ask(all+1) + (t - t/2) * ask(lst+1); } add(now+1, 1); } printf("%lld\n", ans); } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效