zoukankan      html  css  js  c++  java
  • 洛谷月赛 Hello World(升级版)

    题目背景

    T1答案要mod1000000007(10^9+7),请重新提交,非常抱歉!

    一天,智障的pipapi正在看某辣鸡讲义学程序设计。

    题目描述

    在讲义的某一面,他看见了一篇文章。这篇文章由英文字母(大小写均有)、数字、和空白字符(制表/空格/回车)构成。

    pipapi想起了他最近刚刚学会写的Hello World程序。他非常好奇,这篇文章中,“HelloWorld”作为子序列到底出现过多少次呢?

    由于papapi是个智障,大小写对于他而言毫无区别;因此,“hEllOWorLD”这样的子序列也是可以接受的。O和W之间的空格是也是可以少的;也就是说,“HelloWorld”是可以的。根据标程的意思,就是没有空格,不用考虑空格的情况。

    两个子序列相同当且仅当它们每一个字符所在的位置都相同。

    由于答案可能很大,请输出结果对1000000007(10^9+7)的余数。

    输入输出格式

    输入格式: 

    输入包含若干行。这些行的内容共同构成一篇文章。

    文章以EOF(文件结尾)结束。 

    输出格式:

     输出仅包含一个整数,表示这篇文章中“Hello World”出现的次数。 

    输入输出样例

    输入样例#1:
    HhEeLlLlOoWwOoRrLlDd
    输出样例#1:
    1536
    输入样例#2:
    Gou Li Guo Jia Sheng Si Yi
    Qi Yin Huo Fu Bi Qu Zhi
    River can feed people
    Also can race boats
    Hall Ellen Ok Words locked 
    输出样例#2:
    273

    说明

    记n为输入的文章的长度(字符数)。

    对于20%的数据,n <= 20。

    对于50%的数据,n <= 500。

    对于所有的数据,15 <= n <= 500000。


      一道比较裸的dp题,把Helloworld拆成11个状态,"","h","he","hel"以此内推。处理文章。过滤掉所有没有用的字符,重新组成字符串。

    用f[i][j]表示从第1个字符到第i个字符达到第j个状态的方案数。于是可以轻松地得出状态转移方程f[i][j] = f[i - 1][j] + (page[i] == sets[i])? (f[i - 1][j - 1]) : (0)(page表示处理后的文本串,sets[i]表示"helloworld"的第i个字符)。注意初值,在任何位置,组成空字符串的方案只有一种,所以f[i][0] = 1

    Code

     1 /**
     2  * luogu.org
     3  * Problem#2246
     4  * Accepted
     5  * Time:507ms
     6  * Memory:17121k
     7  */
     8 #include<iostream>
     9 #include<cstdio>
    10 #include<cctype>
    11 #include<cstring>
    12 #include<cstdlib>
    13 #include<fstream>
    14 #include<sstream>
    15 #include<algorithm>
    16 #include<map>
    17 #include<set>
    18 #include<queue>
    19 #include<vector>
    20 #include<stack>
    21 using namespace std;
    22 typedef bool boolean;
    23 #define INF 0xfffffff
    24 #define smin(a, b) a = min(a, b)
    25 #define smax(a, b) a = max(a, b)
    26 
    27 #define moder 1000000007
    28 
    29 template<typename T>class Matrix{
    30     public:
    31         T *p;
    32         int lines;
    33         int rows;
    34         Matrix():p(NULL){    }
    35         Matrix(int rows, int lines):lines(lines), rows(rows){
    36             p = new T[(lines * rows)];
    37         }
    38         T* operator [](int pos){
    39             return (p + pos * lines);
    40         }
    41 };
    42 #define matset(m, i, s) memset((m).p, (i), (s) * (m).lines * (m).rows)
    43 
    44 int n;
    45 Matrix<int> f;
    46 
    47 char page[500002];
    48 
    49 inline void init(){
    50     char x;
    51     while(~(x = getchar())){
    52         if(x == 'h' || x == 'H')    page[++n] ='h';
    53         else if(x == 'e' || x == 'E')    page[++n] = 'e';
    54         else if(x == 'l' || x == 'L')    page[++n] = 'l';
    55         else if(x == 'o' || x == 'O')    page[++n] = 'o';
    56         else if(x == 'w' || x == 'W')    page[++n] = 'w';
    57         else if(x == 'r' || x == 'R')    page[++n] = 'r';
    58         else if(x == 'd' || x == 'D')    page[++n] = 'd';
    59     }
    60     f = Matrix<int>(n + 1, 11);
    61     matset(f, 0, sizeof(int));
    62 }
    63 
    64 char sets[12] = " helloworld";
    65 
    66 inline void solve(){
    67     for(int i = 0; i <= n; i++)    f[i][0] = 1;
    68     for(int i = 1; i <= n; i++){
    69         for(int j = 10; j > 0; j--){
    70             (f[i][j] += f[i - 1][j]) %= moder;
    71             if(page[i] == sets[j])    (f[i][j] += f[i - 1][j - 1]) %= moder;
    72         }
    73     }
    74     printf("%d", f[n][10]);
    75 }
    76 
    77 int main(){
    78     init();
    79     solve();
    80     return 0;
    81 }
  • 相关阅读:
    51nod 1494 选举拉票 | 线段树
    51nod 1295 XOR key | 可持久化Trie树
    Codeforces 438D (今日gg模拟第二题) | 线段树 考察时间复杂度的计算 -_-|||
    51nod 1563 坐标轴上的最大团(今日gg模拟第一题) | 线段覆盖 贪心 思维题
    良心的可持久化线段树教程
    51nod 1593 公园晨跑 | ST表(线段树?)思维题
    51nod 1595 回文度 | 马拉车Manacher DP
    51nod 1522 上下序列
    胡小兔的OI日志3 完结版
    51nod 1510 最小化序列 | DP 贪心
  • 原文地址:https://www.cnblogs.com/yyf0309/p/6194982.html
Copyright © 2011-2022 走看看