描述

给一个长度为nn的字符串,问有多少个形式为abb的子序列

思路

  • 一个比较常见的动态规划题目,设dp[i][j]dp[i][j]表示区间[1,i][1,i]中以字母jj为结尾,有多少个形式为ab的子序列,则对于字符串ss最终的答案为i[1,n]dp[i1][s[i]]\sum_{i \in [1,n]}{dp[i-1][s[i]]},同时,dp[i][s[i]]=dp[i1][s[i]]+j[a,z]&js[i]cnt[j]dp[i][s[i]]=dp[i-1][s[i]]+\sum_{j \in [a,z] \& j \neq s[i]}{cnt[j]}cnt[j]cnt[j]为区间[1,i1][1,i-1]中字母jj出现的次数。

  • 由于更新dp[i][s[i]]dp[i][s[i]]仅和i1i-1的各个状态相关,因此可以边循环变dpdp,可以省略一维存储空间

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN=1e5+5;
int cnt[30];
ll dp[MAXN];
char s[MAXN];
int main()
{
    int n;
    scanf("%d",&n);
    scanf("%s",s+1);
    ll sum=0;
    for(int i=1;i<=n;i++)
    {
        int& num=cnt[s[i]-'a'];
        int tot=i-1-num;
        sum+=dp[s[i]-'a'];
        dp[s[i]-'a']+=tot;
        num++;
    }
    printf("%lld\n",sum);
}

时间复杂度O(n)O(n),空间复杂度O(n)O(n)