题目解析 小R的'chi'子序列挑战| 豆包MarsCode AI 刷题

63 阅读3分钟

题目传送门

小R的`chi`子序列挑战 - MarsCode

题意简述

小R定义了一种特别的字符串,称之为可爱串。当且仅当该字符串包含子序列 "chi",并且不包含子串 "chi" 时,称为可爱串。子序列是指字符串中不连续的一段,而子串则必须是连续的字符。目标是计算长度为 n 的、仅由 'c', 'h', 'i' 三种字符组成的字符串中,有多少是可爱串。结果需要对 10^9+7取模。

解题思路

  • 基本概念:

  • 子序列 "chi":字符串中存在字符 'c'、'h'、'i',且顺序为 'c' 在 'h' 之前,'h' 在 'i' 之前。

  • 不包含子串 "chi":字符串中不能有连续的 "chi"。

  • 动态规划:

  • 使用动态规划来计算满足条件的字符串数量。

  • 定义三个数组 f, g, h:

  • f[i] 表示长度为 i 的字符串中可爱串的数量。

  • g[i] 用于辅助计算,表示长度为 i 的字符串中包含子序列 "ch" 的数量。

  • h[i] 表示长度为 i 的字符串中包含子串 "chi" 的数量。

  • 递推关系:

  • g[i] 的计算:通过递推关系,考虑在长度为 i-1 的字符串基础上添加一个字符,形成新的子序列 "ch"。

  • f[i] 的计算:在长度为 i-1 的基础上,考虑添加一个字符形成新的可爱串。

  • h[i] 的计算:通过递推关系,计算包含子串 "chi" 的数量。

4. 结果计算:

  • 最终结果为 f[n] - h[n],即长度为 n 的字符串中可爱串的数量减去包含子串 "chi" 的数量。

代码实现

public class Main {
    private static final int MOD = 1000000007;

    public static long fastexp(long base, long n, long mod) {
        long answer = 1;
        while (n > 0) {
            if (n % 2 == 1) {
                answer = (answer * base) % mod;
            }
            base = (base * base) % mod;
            n /= 2;
        }
        return answer;
    }

    public static int solution(int n) {
        long[] f = new long[n + 1];
        long[] g = new long[n + 1];
        long[] h = new long[n + 1];

        for (long i = 2; i <= n; i++) {
            g[(int) i] = (g[(int) i - 1] * 2 + (i - 1) * fastexp(2, i - 2, MOD)) % MOD;
        }
        for (long i = 3; i <= n; i++) {
            f[(int) i] = ((f[(int) i - 1] * 3) % MOD + g[(int) i - 1]) % MOD;
        }
        for (long i = 3; i <= n; i++) {
            h[(int) i] = (fastexp(3, i - 3, MOD) + h[(int) i - 1] * 3 - h[(int) i - 3]) % MOD;
        }
        return (int) ((f[n] - h[n] + MOD) % MOD);
    }

    public static void main(String[] args) {
        System.out.println(solution(4) == 3);
        System.out.println(solution(5) == 24);
        System.out.println(solution(6) == 126);
    }
}

时间复杂度分析

该算法的时间复杂度为 𝑂(𝑛),因为我们需要遍历长度为 n 的数组来计算 f, g, h 的值。每个数组的计算都涉及到简单的递推关系,因此整体复杂度是线性的。

用到的算法和数据结构

  • 动态规划:用于计算满足条件的字符串数量。

  • 快速幂:用于计算幂次,帮助在递推关系中处理指数增长。

详细分析

在实现过程中,我们使用动态规划来计算满足条件的字符串数量。通过定义 f, g, h 三个数组,我们能够有效地计算出可爱串的数量。g[i] 和 h[i] 的计算帮助我们在递推过程中考虑子序列和子串的影响。最终结果通过 f[n] - h[n] 得到,确保我们只计算符合条件的可爱串。通过对结果取模,我们能够处理大数问题,确保结果在计算过程中不会溢出。