好多牛牛

好多牛牛

题目描述

给出一个字符串S,牛牛想知道这个字符串有多少个子序列等于"niuniu"
子序列可以通过在原串上删除任意个字符(包括0个字符和全部字符)得到。
为了防止答案过大,答案对1e9+7取模

示例输入
“niuniniu”

输出
3

说明
删除第4,5个字符可以得到"niuniu"
删除第5,6个字符可以得到"niuniu"
删除第6,7个字符可以得到"niuniu"

解析

本题目使用动态规划的算法求解。
案例中,在niuniniu中找模式串niuniu,我们在输入串中匹配模式串,模式串中每个字符的匹配次数只和前一个字符有关,因为只有出现了前一个字符,后一个字符才能匹配成功,除了第一个字符(出现一次匹配一次,因为没有前缀)。

输入\模式串匹配次数 n i u n i u
null 0 0 0 0 0 0
n 1 0 0 0 0 0
i 1 1 0 0 0 0
u 1 1 1 0 0 0
n 2 1 1 1 0 0
i 2 3 1 1 1 0
n 3 3 1 2 1 0
i 3 6 1 2 3 0
u 3 6 7 2 3 3

从上表可以看出,每输入一个字符,对应模式串的子串匹配量就增加前一个字符的匹配量,用一个简单的例子表示:

在aaabb中匹配模式串ab,当输入到 b 的时候,a 已经输入了 3 次,因此模式串 ab 的匹配次数要加上模式串前一个字符 a 的匹配次数;当输入第二个 b 的时候,再加上模式串中前一个字符的匹配次数,因此ab一共匹配了6次。

案例中,当输入最后一个u的时候,子串ni已经匹配了6次,即是说,在新输入的u前面,有6个ni可以和新的u组成niu,因此,模式串niu的匹配次数 1(原有)+6=7;子串niuni匹配了3次,模式串niuniu的匹配次数 0+3=3 。

设一个长度为模式串pattern.size()+1的数组dp[],为了统一计算,即每个字符只和前一个字符匹配次数有关,设 dp[0] = 1,这样每次出现模式串的第一个字符,也可以计算dp[1]+=dp[0],即自增。

const int mod = 1e9+7;
class Solution {
public:
    int solve(string s) {
        // write code here
        string pattern = "niuniu";
        vector<int> dp(pattern.size()+1, 0);
        dp[0] = 1;
        
        for(char &c : s)
            for(int i = 0; i < pat.size(); i++)
                if(pattern[i] == c)
                    dp[i+1] = (dp[i+1] + dp[i]) % mod;

        return dp[pattern.size()];
    }
};

你可能感兴趣的:(好多牛牛)