题解 P2246 【SAC#1 - Hello World(升级版)】
啊啊啊,终于AC了……心好累……
这题很明显是DP,因为它满足DP的两个性质——最优子结构、无后效性。(不知道这些的请回去看看DP吧)(划掉)
状态很明显:考虑文本串前i个字符匹配模板前j个字符的匹配数。
转移也很明显:当第i个字符是文本中的第j个,dp[i][j]=dp[i-1][j]+dp[i-1][j-1],其他dp[i][j]=dp[i-1][j](因为这个字符对于匹配没有用嘛)
现在只差一个:边界。
//众:我倒!!!
边界是什么呢?我们知道dp[0][i]=0,但dp[i][0]是几呢?在文本中匹配一个空串?晕。。。
看看样例吧:
HhEeLlLlOoWwOoRrLlDd
现在,我们在文本前加一个奇gay的字符,比如♂【滑稽】
那么文本就变成了:
♂HhEeLlLlOoWwOoRrLlDd
让我们把♂看成模板(即“helloworld”)的第0个字符。这个时候,边界明显了吧。。。
还有一个细节:模板中有重复字符,因此要逆序循环,不然会WA(考虑一下“hhhhhhh”这个模板就明白了)
代码:
#include <iostream>
#include <cstdio>
using namespace std;
const int mod=1000000007;
int main()
{
long long dp[11]={1};
char c,hello[20]="?helloworld";
while((c=getchar())!=EOF)
{
for(int i=10;i>=1;i--)if(c==hello[i]||c+32==hello[i])dp[i]=(dp[i-1]+dp[i])%mod;
}
cout<<dp[10];
return 0;
}