当前位置: 首页 > news >正文

2063. 所有子字符串中的元音

2063. 所有子字符串中的元音

https://leetcode.cn/problems/vowels-of-all-substrings/description/

题目:

给你一个字符串 word ,返回 word 的所有子字符串中 元音的总数 ,元音是指 'a'、'e'、'i'、'o' 和 'u' 。

子字符串 是字符串中一个连续(非空)的字符序列。

注意:由于对 word 长度的限制比较宽松,答案可能超过有符号 32 位整数的范围。计算时需当心。1 <= word.length <= 105
word 由小写英文字母组成

思路1(贡献法)

考虑每个元音字母的贡献。

把字符串长度记作 \(n\) ,考虑字符串中位置 \(i\) (0-based)上的字符 word[i]
如果 word[i] 是元音字母(a,e,i,o,u),那么它出现在多少个子字符串中?

任何包含位置 \(i\) 的子字符串,左端点可以选在 \([0, i]\) 中的任意位置(共 \(i+1\) 种),右端点可以选在 \([i, n-1]\) 中的任意位置(共 \(n-i\) 种)。因此包含这个字符的子字符串一共有

\[(i+1)\times(n-i) \]

种。于是只要把所有元音位置的这个值累加起来就是答案。

时间复杂度 \(O(n)\) ,只需一次线性遍历;空间复杂度 \(O(1)\) 。注意答案可能很大,使用 64 位整型 long long 存储。

例子验证

字符串 "aba"\(n=3\)

  • i=0,'a'\((0+1)*(3-0)=1*3=3\)
  • i=1,'b':不是元音,跳过
  • i=2,'a'\((2+1)*(3-2)=3*1=3\)
    总和 = 6,与你枚举的所有子字符串里的元音总数一致。

C++(OI 风格,详细注释)

#include <bits/stdc++.h>
using namespace std;/** 题目:所有子字符串中的元音* 思路:对每个位置 i,如果是元音,则其贡献为 (i+1)*(n-i)。* 注意:使用 long long 存储答案,防止溢出。** 代码风格:OI 风格,简洁、高效,注释详细。*/inline bool isVowel(char c) {// 只处理小写字母 —— 题目保证输入是小写return c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u';
}int main() {ios::sync_with_stdio(false);cin.tie(nullptr);string word;if (!(cin >> word)) return 0; // 读取输入字符串long long ans = 0;long long n = (long long)word.size(); // 转为 long long 以便后续乘法安全for (long long i = 0; i < n; ++i) {if (isVowel(word[(size_t)i])) {// 位置 i 的贡献为 (i+1) * (n-i)// 都用 long long 计算,避免中间溢出ans += (i + 1) * (n - i);}}cout << ans << '\n';return 0;
}

类似的「每个位置贡献法」可以解决很多子串/区间计数的问题

解法二(DP )

把所有以位置 \(i\)右端点的子字符串看成一组,记 \(dp[i]\) 为“所有以 \(i\) 为右端点的子字符串中,元音的总数”。
考虑从 \(i-1\) 扩展到 \(i\)

  • 新加入的右端为 \(i\) 的子字符串有 \(i+1\) 个(左端可选 0..i)。
  • 对于每个左端 \(k\)\(0\le k\le i\) ),子串 \(s[k..i]\) 的元音数 = 子串 \(s[k..i-1]\) 的元音数 + (若 \(s[i]\) 是元音则 +1 否则 +0)。
  • 把所有左端加起来,得到:

\[dp[i] = dp[i-1] + (i+1) \times [s[i]\text{ 是元音}] \]

(其中 \([s[i]\text{ 是元音}]\) 为 1 或 0)

题目要的就是 所有子字符串中元音的总数,这正好是对每个右端点的贡献求和:

\[\text{ans}=\sum_{i=0}^{n-1} dp[i] \]

这个 DP 与我们之前每个位置直接计算 \((i+1)(n-i)\) 的方法等价,但 DP 思路更容易迁移到类似题型。时间复杂度 \(O(n)\) ,可以把空间压到 \(O(1)\)

举例(快速验证)

字符串 "aba"

  • \(i=0\) :dp0 = 0 + 1*1 = 1
  • \(i=1\) :dp1 = dp0 + 2*0 = 1
  • \(i=2\) :dp2 = dp1 + 3*1 = 4
    ans = 1+1+4 = 6,正确。

C++(OI 风格,详注)

#include <bits/stdc++.h>
using namespace std;/** DP 版解法:* dp[i] 表示所有以 i 为右端点的子串中,元音的总数。* 递推: dp[i] = dp[i-1] + (i+1) * isVowel(s[i])* 最终答案为 sum(dp[i]) (i 从 0 到 n-1)。** 时间:O(n),空间:O(1)(只保存当前 dp 和累加和)*/inline bool isVowel(char c) {// 题目保证小写字母,这里只判断小写元音return c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u';
}int main() {ios::sync_with_stdio(false);cin.tie(nullptr);string s;if (!(cin >> s)) return 0;long long n = (long long)s.size();long long dp_prev = 0;    // dp[i-1]long long ans = 0;        // 最终答案:sum(dp[i])for (long long i = 0; i < n; ++i) {// 如果 s[i] 是元音,则它对所有以 i 为右端点的子串贡献 (i+1)long long contrib = isVowel(s[(size_t)i]) ? (i + 1) : 0;long long dp_i = dp_prev + contrib; // dp[i]ans += dp_i;                         // 累加到答案里dp_prev = dp_i;                      // 更新用于下一轮}cout << ans << '\n';return 0;
}
http://www.rkmt.cn/news/28119.html

相关文章:

  • 已经设置过 settings.json,但是运行 claude 时,依旧提示 Missing API key Run /login
  • 2025 年国内挤塑板厂家最新推荐排行榜:聚焦优质企业,助力建筑保温材料精准选购聚苯乙烯/聚乙烯/广东/优质/高密度挤塑板厂家推荐
  • 一体化预制泵站厂家口碑榜:技术参数与市场表现深度解析
  • 欧拉图笔记
  • 2025年10月抗老面霜推荐榜:五款口碑单品深度对比评测
  • 权威调研榜单:硅溶胶精密铸造生产厂家厂家TOP3榜单好评深度解析
  • 用AI辅助设计登录页
  • 2025 年氧化钙厂家最新推荐榜:综合实力、地理优势与产品特色全景盘点,优选标杆企业
  • 2025年10月抖音代理商推荐榜:华南五强对比与口碑评价
  • 2025年10月投资纠纷律师推荐:权威榜单对比评测与避坑指南
  • 2025年比较好的钢结构艺术楼梯厂家最新推荐榜
  • 完整教程:C# 主窗口 单例 唯一进程 互斥锁
  • 2025年粘度计厂家权威推荐榜:在线/旋转/振动/在线振动/在线旋转/实验室旋转/实验室在线/反应釜在线/管线在线振动/实验室振动粘度计专业选购指南
  • 2025 年国内装修公司最新推荐排行榜:聚焦高端定制与环保需求,精选优质品牌供业主参考苏州高端/装修收纳设计/不锈钢橱柜/别墅装修公司推荐
  • Vue每日一题 父子组件通信
  • Laravel项目接入Nacos配置中心完整部署方案
  • Vue每日一题 - Day 1
  • 2025年每个开发者都必须知道的100多个JavaScript术语(附示例)
  • 2025年知名的氮气电加热器,电加热器厂家推荐及选择指南
  • 0264-CLAP-注解验证参数
  • 0260-CLAP-编写测试函数
  • CSDN博客文章批量导出与文件名规范化实战
  • 0257-CLAP-校验参数范围
  • dls
  • 高压电缆生产厂家口碑榜:基于技术实力、客户服务及市场反馈的专业评估
  • 基于TMS320F28034的全桥LLC电源控制
  • 2025年10月ai优化推荐:主流榜单对比与避坑指南
  • QOJ#12181. abc
  • 行业配置策略
  • Kubernetes 主流网络插件的关键差异对比 - 详解