1 条题解
-
0
📝 题目大意
给定长度为 的字符串 ,定义 为删除 的第 个字符后得到的字符串。求有多少对 满足 且 。
💡 解题思路
-
题目分析:考虑 与 (设 )何时相等。逐字符比对:
- 对于 :,,自然相等。
- 对于 :,。要使二者相等,需要 对所有 成立。
- 对于 :,,自然相等。
因此 当且仅当 ,即 和 落在 的同一个连续相等字符段(run)内。
-
算法推导:将 划分为若干"极大连续相等字符段"。对于长度为 的段,其中任意两个不同位置 都满足 ,贡献为组合数 。遍历字符串,维护变量
a记录当前连续相等字符的个数:- 若 ,则
a++(当前段延续); - 否则,将当前段的贡献 累加到答案
x,并重置a = 1(开始新的一段)。 - 遍历结束后,别忘了加上最后一段的贡献。
- 若 ,则
-
边界与细节:
- ,不存在空串情况。
- 答案可能很大:最坏情况 且全部相同字符,答案为 ,超过 32 位
int范围,必须使用long long(std.cpp中n、a、x均为long long)。 - 当 时,,无需特殊处理。
⏱️ 复杂度分析
- 时间复杂度:仅需一次线性扫描,。
- 空间复杂度:仅使用常数个变量,。
💻 标准代码 (C++)
#include<bits/stdc++.h> using namespace std; int main(){ long long n, a = 1, x = 0; // n: 字符串长度, a: 当前连续相等段长度, x: 答案 string s; cin >> n >> s; for (int i = 1; i < n; i++) { if (s[i - 1] == s[i]) a++; // 当前段延续,长度+1 else { x += a * (a - 1) / 2; // 段结束,累加 C(a, 2) a = 1; // 重置为新段 } } x += a * (a - 1) / 2; // 处理最后一段的贡献 cout << x; } -
- 1
信息
- ID
- 867
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- (无)
- 递交数
- 1
- 已通过
- 1
- 上传者