[洛谷P2246] Hello World

来源:互联网 发布:java mysql学生 编辑:程序博客网 时间:2024/05/29 17:40

题目←

关于次数的dp
发现每个位置的性质除了在此处出现过多少次hello world外,还有其在新的hello world中可能的位置
设g[i][j]为以i为终点,构成helloworld的前j位的方案数
例如在字符串hhelloworld中,g[3][2] = 2;
于是发现
g[i][j] = i1k=1g[k][j - 1],
使用前缀和维护,用sum[j - 1]更新g[i][j],用g[i][j]更新sum[j];
f[i]表示当前位出现过多少完整的helloworld
发现f[i]仅能由g[i][10]更新,即出现新的以i结尾的构成前10位(全串)的方案数
对答案贡献为g[i][10]

#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#define mod 1000000007#define LL long longusing namespace std;const int MAXN = 500000 + 50;int n;string s,x;LL sum[MAXN],f[MAXN],g[MAXN][15];char c;int main(){    while(cin >> x){        s += x;    }    n = s.length();    for(int i = 0;i < n;i++){        if(s[i] >= 'A' && s[i] <= 'Z')s[i] += 32;    }    for(int i = 0;i < n;i++){        f[i] = f[i - 1];        if(s[i] == 'h'){            g[i][1] = 1;            sum[1]++;        }        else if(s[i] == 'e'){            g[i][2] = (sum[1]%mod + g[i][2]%mod)%mod;            sum[2] = (g[i][2]%mod + sum[2]%mod)%mod;        }        else if(s[i] == 'l'){            g[i][3] += sum[2];            g[i][3] %= mod;            g[i][4] += sum[3];            g[i][4] %= mod;            g[i][9] += sum[8];            g[i][9] %= mod;            sum[4] += g[i][4];            sum[4] %= mod;            sum[3] += g[i][3];            sum[3] %= mod;            sum[9] += g[i][9];            sum[9] %= mod;        }        else if(s[i] == 'o'){            g[i][5] += sum[4];            g[i][5] %= mod;            g[i][7] += sum[6];            g[i][7] %= mod;            sum[7] += g[i][7];            sum[7] %= mod;            sum[5] += g[i][5];            sum[5] %= mod;        }        else if(s[i] == 'w'){            g[i][6] += sum[5];            g[i][6] %= mod;            sum[6] += g[i][6];            sum[6] %= mod;        }        else if(s[i] == 'r'){            g[i][8] += sum[7];            g[i][8] %= mod;            sum[8] += g[i][8];            sum[8] %= mod;        }        else if(s[i] == 'd'){            g[i][10] += sum[9];            g[i][10] %= mod;            sum[10] += g[i][10];            sum[10] %= mod;             f[i] += g[i][10];//sum[10]包含了所有以前的串,g[i][10]为该位结尾的所有helloworld,故新增g[i][10]             f[i] %= mod;        }    }    printf("%lld",f[n - 1]);    return 0;}

Tips:
明确各个数组的含义,保证在转移的时候符合实际


11.5
哇我好菜啊
我记录了那么多无用数组
直接把sum和g那个数组合并不就行了吗
还有f不就是一个变量吗
srO

#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#define mod 1000000007using namespace std;const int MAXN = 500000 + 50;int dp[MAXN][15];char s[] = {'#','h','e','l','l','o','w','o','r','l','d'};string a,x;char ss[MAXN];int len,ans;int main(){    while(cin >> x){        a += x;    }    len = a.length();    for(int i = 0;i < len;i ++){        if(a[i] >= 'A' && a[i] <= 'Z'){            a[i] += 32;        }        ss[i + 1] = a[i];    }    dp[0][0] = 1;    for(int i = 1;i <= len;i ++){        for(int j = 0;j <= 10;j ++){            dp[i][j] = dp[i - 1][j];            if(ss[i] == s[j] && j){                dp[i][j] = (dp[i - 1][j - 1]%mod + dp[i][j])%mod;                if(j == 10)ans = (ans + dp[i - 1][j - 1])%mod;            }        }    }    cout << ans;}