题解 | #abb#

abb

https://www.nowcoder.com/practice/0a8bbf8b9b5b4280957849ef4f240f07

初读题目没有太多思路,只觉得暴力穷举时间复杂度太高,应该过不了。看一了下排行榜里的代码,没有太多注释,看不太明白。理解了一会,按照我自己的理解添加了一些注释。

主要是理解 dp 数组的含义,sum数组表示的是 26 个字母出现的次数,dp 数组存储的是 26个字母能形成ab形式的个数。遍历的时候,idx 为 当前字母在 26字母表中的位置,abb个数的总计数器需要 + dp[idx],表示前面可以形成 ab 形式的子序列加上当前的这个字母,就能形成abb的形式。dp 的更新则是在计数器更新之后,dp 只需要 + 前面的字符串中不为 当前字母的数量(即第一个字符 与 第二个字符不一样的个数,即为 当前索引 i - 当前字母出现的次数 sum[idx])。表达不太清晰的位置望理解。

import java.util.Scanner;
import java.io.*;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine());
        String str = br.readLine();
        long[] sum = new long[26];  // sum[i] 表示 字母表中第 i 个字母,在 str 中 出现的次数
        long[] dp = new long[26];  // dp[i] 表示 字母表中第 i 个字母,在 str 中 可以组成 ab 的个数,当再次遇到 第 i 个字母的时候,能组成abb的个数 + dp[i] 即可
        long result = 0;
        
        // 遍历 str,取出每一个 char,计算在字母表中的 idx (是字母表中的第几个)
        for (int i = 0; i < n; i++) {
            int index = str.charAt(i) - 'a';
            // 计数器 加上 dp[idx](dp[idx] 表示前面的 子序列中 当前字母 char 能形成 ab 形式的个数,前面能形成 ab 的序列 + 当前的 char 即可形成 abb 的形式)
            result += dp[index];
            // 更新 dp:当前 在字符串中的 索引 - 当前字符 char 出现的次数,即 前面有多少个不为 char 的字符
            dp[index] += i - sum[index];
            // 计数 char 出现的次数
            sum[index]++;
        }
        System.out.println(result);
    }
}

全部评论

相关推荐

03-10 14:19
已编辑
重庆邮电大学 前端工程师
球Offer上岸👑:测试也难求一面 逆天
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务