遗忘的记忆

[题目链接](https://www.nowcoder.com/practice/8246aab6553d4384ba5f4090101762ef)

思路

篇分享,每篇的点赞量为 的正整数。给定一个长度为 的字符串 ,其中 <=>,描述第 篇和第 篇点赞量的大小关系。求满足所有约束的点赞量序列有多少种,答案对 取模。

动态规划 + 前缀和

定义 表示第 篇分享点赞量为 时的合法方案数。

初始状态,对所有

转移:根据 的字符,从 转移到

  • <(第 篇严格大于第 篇):

$$

的前缀和,到 为止。

  • >(第 篇严格小于第 篇):

$$

的后缀和,从 开始。

  • =(第 篇等于第 篇):

$$

对于 <> 的情况,前缀和与后缀和可以在遍历 的过程中累加维护,无需额外数组,单次转移

最终答案为

样例演示

输入 <=>

  • 初始:(对应
  • 经过 <(前缀和偏移一位)
  • 经过 =(不变)
  • 经过 >(后缀和偏移一位)
  • 答案

复杂度分析

  • 时间复杂度:,共 次转移,每次遍历 个值。
  • 空间复杂度:,使用滚动数组优化,只保留当前一行。

代码

#include <bits/stdc++.h>
using namespace std;

const int MOD = 1e9 + 7;

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, m;
    cin >> n >> m;
    string s;
    if(n > 1) cin >> s;

    vector<long long> dp(m + 2, 0);
    for(int j = 1; j <= m; j++) dp[j] = 1;

    for(int i = 0; i < (int)s.size(); i++){
        vector<long long> ndp(m + 2, 0);
        if(s[i] == '<'){
            long long pre = 0;
            for(int j = 1; j <= m; j++){
                ndp[j] = pre;
                pre = (pre + dp[j]) % MOD;
            }
        } else if(s[i] == '>'){
            long long suf = 0;
            for(int j = m; j >= 1; j--){
                ndp[j] = suf;
                suf = (suf + dp[j]) % MOD;
            }
        } else {
            for(int j = 1; j <= m; j++){
                ndp[j] = dp[j];
            }
        }
        dp = ndp;
    }

    long long ans = 0;
    for(int j = 1; j <= m; j++) ans = (ans + dp[j]) % MOD;
    cout << ans << endl;
    return 0;
}
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        final int MOD = 1000000007;
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt(), m = sc.nextInt();
        String s = "";
        if (n > 1) s = sc.next();

        long[] dp = new long[m + 2];
        for (int j = 1; j <= m; j++) dp[j] = 1;

        for (int i = 0; i < s.length(); i++) {
            long[] ndp = new long[m + 2];
            char c = s.charAt(i);
            if (c == '<') {
                long pre = 0;
                for (int j = 1; j <= m; j++) {
                    ndp[j] = pre;
                    pre = (pre + dp[j]) % MOD;
                }
            } else if (c == '>') {
                long suf = 0;
                for (int j = m; j >= 1; j--) {
                    ndp[j] = suf;
                    suf = (suf + dp[j]) % MOD;
                }
            } else {
                for (int j = 1; j <= m; j++) {
                    ndp[j] = dp[j];
                }
            }
            dp = ndp;
        }

        long ans = 0;
        for (int j = 1; j <= m; j++) ans = (ans + dp[j]) % MOD;
        System.out.println(ans);
    }
}