题意:给定一个句子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]这段字符的情况下,拥有的方案数,+我的转义,就是一种全新的方案,所以匹配到这个字符的时候,方案数要加上屏蔽这段字符前拥有的方案数

  1. #include <cstdio>
  2. #include <cstdlib>
  3. #include <cstring>
  4. #include <cmath>
  5. #include <algorithm>
  6. using namespace std;
  7. #define inf (0x3f3f3f3f)
  8. typedef long long int LL;
  9. typedef unsigned long long int ULL;
  10. #include <iostream>
  11. #include <sstream>
  12. #include <vector>
  13. #include <set>
  14. #include <map>
  15. #include <queue>
  16. #include <string>
  17. const int maxn = +;
  18. char str[maxn];
  19. char sub[maxn];
  20. LL dp[maxn];
  21. const int MOD = 1e9+;
  22. ULL sumhash[maxn];
  23. ULL powseed[maxn];
  24. const int seed = ;
  25. ULL calc (int begin,int end)
  26. {
  27. return sumhash[end] - powseed[end-begin+]*sumhash[begin-];
  28. }
  29. int f;
  30. void work ()
  31. {
  32. scanf("%s%s",str+,sub+);
  33. int lenstr = strlen(str+);
  34. int lensub = strlen(sub+);
  35. ULL sub_hash = ;
  36.  
  37. for (int i=;i<=lensub;++i) sub_hash = sub_hash*seed + sub[i];
  38. for (int i=;i<=lenstr;++i) sumhash[i] = sumhash[i-]*seed + str[i];
  39.  
  40. for (int i=;i<=lensub;++i) dp[i]=;
  41. // printf ("%I64u\n",sub_hash);
  42. // printf ("%I64u\n",sumhash[4]);
  43. for (int i=lensub;i<=lenstr;++i)
  44. {
  45. dp[i] = dp[i-];
  46. //printf ("%d %d %I64u\n",i-lensub+1,i,calc(i-lensub+1,i));
  47. if (calc(i-lensub+,i) == sub_hash)
  48. {
  49. dp[i] += dp[i-lensub];
  50. }
  51. dp[i] %= MOD;
  52. }
  53. printf ("Case #%d: %I64d\n",++f,dp[lenstr]);
  54. return ;
  55. }
  56.  
  57. int main()
  58. {
  59. #ifdef local
  60. freopen("data.txt","r",stdin);
  61. #endif
  62. powseed[]=;
  63. for (int i=;i<=maxn-;++i) powseed[i] = powseed[i-]*seed;
  64. int t;
  65. scanf("%d",&t);
  66. while (t--) work();
  67. return ;
  68. }

这题也可以用kmp做的

就是kmp匹配一次后,用个isok数组保存str的第i位能否匹配成功就可以了

  1. #include <cstdio>
  2. #include <cstdlib>
  3. #include <cstring>
  4. #include <cmath>
  5. #include <algorithm>
  6. using namespace std;
  7. #define inf (0x3f3f3f3f)
  8. typedef long long int LL;
  9. typedef unsigned long long int ULL;
  10. #include <iostream>
  11. #include <sstream>
  12. #include <vector>
  13. #include <set>
  14. #include <map>
  15. #include <queue>
  16. #include <string>
  17. const int maxn = +;
  18. char str[maxn];
  19. char sub[maxn];
  20. LL dp[maxn];
  21. bool isok[maxn];
  22. const int MOD = 1e9+;
  23. int f;
  24. void get_next (char sub[],int nextliu[],int len)
  25. {
  26. int i=,j=;
  27. nextliu[]=;//记得初始值不能忘记
  28. //next[len+1]这个也有值了 后面的++i和++j先加后赋值
  29. while (i<=len)
  30. {
  31. //sub[i]的含义,后缀的单个字符
  32. //sub[j]的含义,前缀的单个字符
  33. if (j== || sub[i]==sub[j])//考虑的是上一个的
  34. {
  35. nextliu[++i]=++j; //用是上一个的比较,值的当前的值
  36. }
  37. else j=nextliu[j];
  38. }
  39. return ;
  40. }
  41. int nextliu[maxn];
  42. int kmp (char str[],char sub[],int pos)
  43. {
  44. int len1=strlen(str+);
  45. int len2=strlen(sub+);
  46. //int next[maxn]={0};//maxn为最大长度
  47. get_next(sub,nextliu,len2);//得到next[]数组
  48. int i=pos;//从哪里出发
  49. int j=;
  50. int ans=;
  51. while (i<=len1)
  52. {
  53. if (j== || str[i]==sub[j])
  54. {
  55. i++;j++;
  56. }
  57. else j=nextliu[j];
  58. if (j==len2+)//有一个了
  59. {
  60. isok[i-]=; //标记这个位置是OK的
  61. ans++;
  62. j=nextliu[j];//回溯匹配
  63. //i值不用回溯的
  64. }
  65. }
  66. return ans;
  67. }
  68.  
  69. void work ()
  70. {
  71. scanf("%s%s",str+,sub+);
  72. int lenstr = strlen(str+);
  73. int lensub = strlen(sub+);
  74. memset(isok,,sizeof isok);
  75. kmp(str,sub,);
  76. for (int i=;i<=lensub;++i) dp[i]=;
  77. // for (int i=1;i<=lenstr;++i)
  78. // {
  79. // printf ("%d ",isok[i]);
  80. // }
  81. // printf ("\n");
  82. for (int i=lensub;i<=lenstr;++i)
  83. {
  84. dp[i]=dp[i-];
  85. if (isok[i]) dp[i] += dp[i-lensub];
  86. dp[i] %= MOD;
  87. }
  88. printf ("Case #%d: %I64d\n",++f,dp[lenstr]);
  89. return ;
  90. }
  91.  
  92. int main()
  93. {
  94. #ifdef local
  95. freopen("data.txt","r",stdin);
  96. #endif
  97. int t;
  98. scanf("%d",&t);
  99. while (t--) work();
  100. return ;
  101. }

Count the string

HDU - 3336

统计所有前缀在本串中出现的次数和

kmp + dp

利用next数组。

给定一个长为lenstr(<=20W)的字符串,要求找出所有前缀在本串中出现的次数,在这里前缀有,"a","ab","aba","abab" ans=2+2+1+1=6。思路:利用next[]的意义,最大的前缀和后缀匹配,那么,设dp[i]表示以第i个字符串结尾的所有子串(记住一定要是第i个字符串结尾,不要以为dp[n]就是答案,子串还有很多),和前i个字符的前缀(前缀一定是:s[1],s[1]s[2],s[1]s[2]s[3],这样的,不能是s[2]s[3]这样的。)所匹配的数目。那么,既然前缀和后缀相同,abab*****abab,那么,我的dp[i]=dp[next[i+1]-1]+1。(+1)是为了加上自己那个串,出现了一次。

  1. #include <cstdio>
  2. #include <cstdlib>
  3. #include <cstring>
  4. #include <cmath>
  5. #include <algorithm>
  6. using namespace std;
  7. #define inf (1<<28)
  8. typedef long long int LL;
  9.  
  10. #include <iostream>
  11. #include <sstream>
  12. #include <vector>
  13. #include <set>
  14. #include <map>
  15. #include <queue>
  16. #include <string>
  17. const int MOD = ;
  18. const int maxn = +;
  19. char str[maxn];
  20. void get_next (char sub[],int nextliu[],int len)
  21. {
  22. nextliu[]=;
  23. int i=,j=;
  24. while (i<=len)
  25. {
  26. if (j== || sub[i]==sub[j])
  27. {
  28. nextliu[++i]=++j;
  29. }
  30. else j=nextliu[j];
  31. }
  32. return ;
  33. }
  34. int nextliu[maxn];
  35. int dp[maxn]={};
  36. void work ()
  37. {
  38. int lenstr;
  39. scanf ("%d",&lenstr);
  40. scanf ("%s",str+);
  41. get_next(str,nextliu,lenstr);
  42. /*
  43. for (int i=1;i<=lenstr;i++)
  44. {
  45. printf ("%d ",next[i]);
  46. }
  47. printf ("\n");*/
  48.  
  49. int ans=;
  50. for (int i=;i<=lenstr;i++)
  51. {
  52. dp[i]=dp[nextliu[i+]-]+;
  53. ans += dp[i];
  54. ans %= MOD;
  55. }
  56. printf ("%d\n",ans);
  57. return ;
  58. }
  59.  
  60. int main ()
  61. {
  62. #ifdef local
  63. freopen("data.txt","r",stdin);
  64. #endif
  65. int t;
  66. scanf ("%d",&t);
  67. while (t--)
  68. {
  69. work ();
  70. }
  71. return ;
  72. }

HDU 5763 Another Meaning dp+字符串hash || DP+KMP的更多相关文章

  1. HDU 5763 Another Meaning

    HDU 5763 Another Meaning 题意:一个字串有可能在模式串出现多次,问有多少种可能出现的情况.关键是有重合的字串是不能同时计入的. 思路:先用kmp求出所有字串的位置.然后,dp. ...

  2. HDU 5763 Another Meaning KMP+DP

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5763 Another Meaning Time Limit: 2000/1000 MS (Java/ ...

  3. CodeForces7D 字符串hash + dp

    https://cn.vjudge.net/problem/20907/origin 长度是 n 的字符串 s,如果它自身是回文数,且它的长度为 的前缀和后缀是 (k - )-回文数,则它被称作 k- ...

  4. [CQOI2014][bzoj3507] 通配符匹配 [字符串hash+dp]

    题面 传送门 思路 0x01 KMP 一个非常显然而优秀的想法:把模板串按照'*'分段,然后对于每一段求$next$,'?'就当成可以对于任意字符匹配就行了 对于每个文本串,从前往后找第一个可以匹配的 ...

  5. HDU 1880 魔咒词典 (字符串hash)

    <题目链接> 题目大意: 就是每个字符串有一个配套的对应字符串,询问的时候,无论输出其中的哪一个字符串,输出另一个,如果不存在这个字符串,直接输出"what?". 解题 ...

  6. HDU 5763 Another Meaning (kmp + dp)

    Another Meaning 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5763 Description As is known to all, ...

  7. HDU 5763 Another Meaning(DP+KMP)

    http://acm.hdu.edu.cn/showproblem.php?pid=5763 题意: 给出一个字符串和一个模式串,模式串有两种意思,问这句话有几种意思. 思路:因为肯定要去字符串去找模 ...

  8. TTTTTTTTTTTTTT hdu 5763 Another Meaning 哈希+dp

    Another Meaning Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)T ...

  9. HDU 5763 Another Meaning (KMP/哈希+DP)

    题目大意:给你两个串,一长一短,如果长串中某个子串和短串完全相同,则这个子串可以被替换成"#",求长串所有的表达形式....... 比如"hehehehe"和& ...

随机推荐

  1. HDOJ1238(string)

    Substrings Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total ...

  2. JavaScript-Tool:jquery.cookie.js

    ylbtech-JavaScript-Tool:jquery.cookie.js 1.返回顶部 1.jquery.cookie.js /*! * jQuery Cookie Plugin v1.4.0 ...

  3. C语言计算日期间隔天数的经典算法解析

    #include <stdio.h> #include <stdlib.h> int day_diff(int year_start, int month_start, int ...

  4. phpstorm断点调试 php.ini 文件中 Xdebug 配置

    [XDebug]xdebug.profiler_output_dir="D:\phpStudy\tmp\xdebug"xdebug.trace_output_dir="D ...

  5. jsp 路径问题

    <script   type="text/javascript"   src="<%=ApplicationContextUtil.getBasePath(r ...

  6. 为JFileChooser设定扩展名过滤

    --------------------siwuxie095                             工程名:TestFileChooser 包名:com.siwuxie095.fil ...

  7. 杭电acm 1032题

    The Problem问题 Consider the following algorithm:考虑下面的算法: 1 2 3 4 5 6 input n print n if n = 1 then st ...

  8. angular使用base64的encode和decode

    var app = angular.module("encodeDecode", []); app.controller("encodeDecodeCtrl", ...

  9. Error creating form bean of class com.onlinebookstore.presentation.CatalogBean

    Error creating form bean of class com.onlinebookstore.presentation.CatalogBean 可能是action form未编译 这个问 ...

  10. Postman使用-1

    文章来源:http://www.cnplugins.com/tool/specify-postman-methods.html https://www.cnblogs.com/Skyyj/p/6856 ...