码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 5763 Another Meaning dp+字符串hash

时间:2016-08-22 19:51:05      阅读:139      评论:0      收藏:0      [点我收藏+]

标签:

题意:给定一个句子str,和一个单词sub,这个单词sub可以翻译成两种不同的意思,问这个句子一共能翻译成多少种不能的意思

例如:str:hehehe   sub:hehe 那么,有**he、he**、和hehehe三种不同的意思,

考虑一下aaadaaa这种情况?sub:aa  前面的aaa有三种,后面的aaa有三种,所以一共应该是有9种情况。

可以考虑成3*3=9

如果你考虑分块去相乘的话,那么恭喜你,你GG了。因为这样写非常复杂,而且非常难判断。

可以考虑下dp,因为注意到,它每个单词只有两种状态,要么转换成其他意思,要么就保留原意。

记dp[i]为匹配到str的第i个字符,所拥有的方案数,那么,如果不转换意思,dp[i] = dp[i-1]

就是方案数是没增加的,还是原来拥有的总数。

那么考虑转义。需要str[i-lensub+1...i]这段字符和sub一模一样,你才能转义把?

这里可以用字符串hash的方法O(1)判断

那么dp[i] += dp[i-lenstub];

就是在屏蔽str[i-lensub+1...i]这段字符的情况下,拥有的方案数,+我的转义,就是一种全新的方案,所以匹配到这个字符的时候,方案数要加上屏蔽这段字符前拥有的方案数

技术分享
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;
typedef unsigned long long int ULL;
#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
const int maxn = 100000 +20;
char str[maxn];
char sub[maxn];
LL dp[maxn];
const int MOD = 1e9+7;
ULL sumhash[maxn];
ULL powseed[maxn];
const int seed = 131;
ULL calc (int begin,int end)
{
    return sumhash[end] - powseed[end-begin+1]*sumhash[begin-1];
}
int f;
void work ()
{
    scanf("%s%s",str+1,sub+1);
    int lenstr = strlen(str+1);
    int lensub = strlen(sub+1);
    ULL sub_hash = 0;

    for (int i=1;i<=lensub;++i) sub_hash = sub_hash*seed + sub[i];
    for (int i=1;i<=lenstr;++i) sumhash[i] = sumhash[i-1]*seed + str[i];

    for (int i=0;i<=lensub;++i) dp[i]=1;
   // printf ("%I64u\n",sub_hash);
    // printf ("%I64u\n",sumhash[4]);
    for (int i=lensub;i<=lenstr;++i)
    {
        dp[i] = dp[i-1];
        //printf ("%d %d %I64u\n",i-lensub+1,i,calc(i-lensub+1,i));
        if (calc(i-lensub+1,i) == sub_hash)
        {
            dp[i] += dp[i-lensub];
        }
        dp[i] %= MOD;
    }
    printf ("Case #%d: %I64d\n",++f,dp[lenstr]);
    return ;
}

int main()
{
#ifdef local
    freopen("data.txt","r",stdin);
#endif
    powseed[0]=1;
    for (int i=1;i<=maxn-20;++i) powseed[i] = powseed[i-1]*seed;
    int t;
    scanf("%d",&t);
    while (t--) work();
    return 0;
}
View Code

 

HDU 5763 Another Meaning dp+字符串hash

标签:

原文地址:http://www.cnblogs.com/liuweimingcprogram/p/5796758.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!