子串分值
1.试题 C :直线2.树形动态规划3.X 进制减法4.后缀表达式5.统计子矩阵6.包子凑数7.整数拼接8.地宫取宝9.七段码10.砝码称重11.递增三元组12.完全平方数13.[蓝桥杯 2019 省 A] 填空问题 E14.波动数列15.左孩子右兄弟16.接龙数列17.糖果18.蚂蚁感冒
19.子串分值
20.超级胶水21.P9425 [蓝桥杯 2023 国 B] AB 路线22.P9426 [蓝桥杯 2023 国 B] 抓娃娃23.P9425 [蓝桥杯 2022 国 B] 202224.P8805 [蓝桥杯 2022 国 B] 机房25.P8806 [蓝桥杯 2022 国 B] 搬砖26.P8764 [蓝桥杯 2021 国 BC] 二进制问题一、题目描述
二、问题简析
记录字符串 \(s\) 的 第 \(i\) 个字符 \(s_i\)(\(0\leq i<s.size\))上一次出现的位置 \(pre_i\)、下一次出现的位置 \(nex_i\),仅包含 \(s_i\) 的字串个数为 \((i - (pre_i + 1) + 1) * (nex_i - 1 - i + 1)\),即 \((i-pre_i)*(nex_i-i)\)。只需要遍历所有的 \(s_i\),将所有字串个数相加就是所求。
\(pre_i\):因为字符串里只有 \(26\) 个小写字母,所以创建一个容量为 \(26\) 的临时数组 rec[26]
,记录对应字母上次出现的下标(rec[0]
对应 a
,rec[1]
对应 b
,以此类推)。
- 1、因为要记录上一次出现的位置,所以要从左往右遍历,并更新相应的
rec[i]
。 - 2、需要注意每个字母首次出现的 \(pre_i\),因为是首次出现,所以下标从 \(0\) 至 \(i\) 的字母都可以是字串的开头,即 \(pre_i+1==0\)。因此,
rec[26]
要初始化为-1
。
\(nex_i\):与 \(pre_i\) 类似,也需要一个临时数组 rec[26]
。不同点:
- 1、从右往左遍历,并更新相应字母的下标
- 2、
rec[26]
初始化为s.size
,因为每个字母最后一次出现时,下标从 \(i\) 至 \(s.size-1\) 都可以作为字串的结尾,即 \(nex_i-1==s.size-1\)。
三、AC代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAX = 1e5 + 3;
int pre[MAX], nex[MAX], rec[30];
string s;
int main()
{
#ifdef LOCAL
freopen("test.in", "r", stdin);
#endif
cin >> s;
int sSize = s.size();
fill(rec, rec + 26, -1);
for (int i = 0; i < sSize; i++)
{
pre[i] = rec[s[i] - 'a'];
rec[s[i] - 'a'] = i;
}
fill(rec, rec + 26, sSize);
for (int i = sSize - 1; i >= 0; i--)
{
nex[i] = rec[s[i] - 'a'];
rec[s[i] - 'a'] = i;
}
ll ans = 0;
for (int i = 0; i < sSize; i++)
{
ans += (i - pre[i]) * (nex[i] - i);
}
cout << ans << endl;
return 0;
}
完
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具