引言:
为什么我要看了别人的代码才会题,呜呜呜。好了,这道题我觉得很有必要记录一下,我觉得这些大佬的想法太厉害了,所以我就把它借鉴过来了。
题目:
I love you
链接:https://ac.nowcoder.com/acm/contest/3947/I
来源:牛客网
题目描述
此时相望不相闻,愿逐月华流照君。
一纸情书,到底蕴含了多少倍的爱情呢?
I love you, not only for what you are, but for what I am when I am with you.
输入描述:
共一行:一封若干个字符的情书(大小写不敏感)。
情书不会超过684594个字符(大写、小写字母)。
输出描述:
共一行:包含一个整数,即iloveyou在情书中作为子序列出现的次数。
由于答案可能很大,请输出对20010905取模后的值。
示例1
输入
复制
IloveyouNotonlyforwhatyouareButforwhatIamWhenIamwithyouIloveyouNotonlyforwhatYouhavemadeofyourselfButforwhatYouaremakingofme
输出
复制
2864
解法:
以我的脑回路咋可能想到dp,我就只会暴力暴力再暴力,然后这道题暴力我都不知道咋暴力。大佬的做法是这样的,I love you一共八个字母构成一个字符串,由于不区分大小写,我们用tolower(这可是c语言里面提供的函数哦,是不是忘了呢)转成小写来考虑。对于dp[i]表示的是前i个字母构成的前缀的总个数,那么dp[8]就是我们的答案了。
实现:
关键来了,我们dp[1]每当遇到字母i就让他++,这完全没毛病,他自己就是一个前缀。对于dp[2]呢,这就不一样了,我们想一想是不是前面有多少个dp[1],我们就能构成多少个IL这样的前缀呢,也就是说dp[2]=dp[2]+dp[1]%mod。对于ILO也是一样的操作,依次类推罢了。不过,要注意的是我们有两个o,那遇到了怎么办呢,完全没关系,但是你要对两个有o的地方都进行更新。比如,现在我们遇到了一个o,那么对于dp[3],我们前面已经对dp[2]进行了更新,故它将会更新。而对于后面那个dp[7]的o,由于我们还没有对dp[6]进行更新,故它的值不会改变,直到我们在给定字符串中找到了前面的所有前缀,才会对他进行更新。所以下面的代码里面我们用的是if而没有用else if。
代码:
#include<bits/stdc++.h>
using namespace std;
const int mod=20010905;
int dp[10];
typedef long long ll;
void solve(){
string s;
cin>>s;
for(int i=0;i<s.length();i++){
char x=tolower(s[i]);
if(x=='i'){
dp[1]++;
}
if(x=='l'){
dp[2]=(dp[2]+dp[1])%mod;
}
if(x=='o'){
dp[3]=(dp[3]+dp[2])%mod;
}
if(x=='v'){
dp[4]=(dp[4]+dp[3])%mod;
}
if(x=='e'){
dp[5]=(dp[5]+dp[4])%mod;
}
if(x=='y'){
dp[6]=(dp[6]+dp[5])%mod;
}
if(x=='o'){
dp[7]=(dp[7]+dp[6])%mod;
}
if(x=='u'){
dp[8]=(dp[8]+dp[7])%mod;
}
}
cout<<dp[8]<<endl;
}
int main(){
solve();
return 0;
}
项目类代码写多了,不喜欢main函数里面一堆东西,还是这样舒服。