关键:f[i][j]这个数组表示改造字符串前i个字符使其与niuniu这个字符串前j个相同的个数。则最终的结果就是f[n][6],即s前n个字符共可以改造几次得到niuniu这个字符串。
初始化
for(int i=0;i<=n;i++)
{
f[i][0]=1;
}
该初始化表示将字符串前i个变为空字符的方法有几种。显然只有一种方案即全部清空。
状态转移方程:
当s[i]==s1[j]时,说明这个是s[i]字符可以出现在s1字符串中。这个字符有两种选择要么让它加入构成niuniu,要么删除它。所以f[i][j]=f[i-1][j]+f[i-1][j-1],其中f[i-1][j]表示用前i-1个字符构成niuniu前j个字符串的所有方案的个数,即不要第i个字符。而f[i-1][j-1]表示前i-1个字符构成niuniu的前j-1个字符串的所有方案的个数,这是说明留下了s[i]。
当s[i]!=s1[j],则s[i]只能被舍弃,即f[i][j]=f[i-1][j]。
const int N=10010;
int f[N][10];
long long mod=1e9+7;
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param s string字符串
* @return int整型
*/
int solve(string s) {
int n=s.size();
string s1=" niuniu";
cout<<s1[4]<<endl;
//f[i][j]表示从字符串s的0到i与s1的0到j匹配的字符串的个数
for(int i=0;i<=n;i++)
{
f[i][0]=1;
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=6;j++)
{
if(s[i-1]==s1[j])//当第i个字符与niuniu的第j+1个匹配的时候有两种选择
{
f[i][j]=f[i-1][j]+f[i-1][j-1];//使用s[i]匹配为f[i][j],不使用为f[i][j-1]
}
else
{
f[i][j]=f[i-1][j];
}
f[i][j] %= mod;
}
}
return f[n][6];
// write code here
}
};