再入DP:寻找SCAU

Description
我们知道华农校园里很多地方都有SCAU(South China Agricultural University)的标志,如五山一条街旁边的草坪就有一个绿绿的"SCAU"。
小To今年刚考进了华农,他来到学校寻找着校园内SCAU的标志。
现在小To得到了一个字符串,他想知道这个字符串里有多少个SCAU的子序列(不必是连续的,但是有序的)

输入格式
一个只包含S、C、A、U四种字母(大写)的字符串s, 且1<= |s| <= 100000,其中|s|是字符串s的长度

输出格式
输出字符串s中SCAU序列的个数,由于答案可能会很大,请对其求模1000000007(1e9+7)后输出

输入样例
SCAUUU

输出样例
3

分析:
一开始的想法是把S、C、A、U的个数分别存下来,然后相乘,后来想了一下发现这是错误的想法,因为SCAU是要有序的,这样算得的子序列其实是无序的,那么究竟要怎么做呢?类比求最长上升子序列,我们能不能把SCAU看成一个上升的序列,即字符C比字符S大,字符A比字符C大,字符U比字符A大,那么,求该字符串有多少个SCAU子序列可分解为每个U前有多少个SCA序列,把每个U前SCA序列个数相加即可;而求SCA序列共有多少个可以分解为每个A前有多少个SC序列,再把每个A前SC序列个数相加即可;求SC序列总数则可分解为每个C前有多少个S,再把每个C前S个数相加即可。

#include <stdio.h>
char ch[100005];
const int M=1e9+7;
int main()
{
    int s=0,c=0,a=0,u=0,i;//s代表到该字符为止序列S的个数,c代表到该字符为止序列SC的个数,a代表到该字符为止序列SCA的个数,u代表到该字符为止SCAU的序列。
    scanf("%s",ch);
    for(i=0; ch[i] != '\0'; i++)
    {
        if(ch[i] == 'S')//如果当前字符为S,那么序列S的个数加一
            s++;
        if(ch[i] == 'C')//如果当前字符为C,那么序列SC的个数等于之前所求的SC的个数再加上该字符前S的个数
            c =(c+s)%M;
        if(ch[i] == 'A')//如果当前字符为A,那么序列SCA的个数等于之前所求的SCA的个数加上该字符前SC的个数
            a =(a+c)%M;
        if(ch[i] == 'U')//如果当前字符为U,那么序列SCAU的个数等于之前所求的SCAU的个数加上该字符前SCA的个数
            u =(u+a)%M;
    }
    printf("%d",u);
}

第一次提交wa了。。。原因竟是……!!忘记求模了。。。震撼我妈

猜你喜欢

转载自blog.csdn.net/weixin_43678350/article/details/84797999