依稀记得,$NOIP$之前的我是如此的弱小....

完全不会$KMP$的写法,只会暴力$hash$....

大体思路为把一个串的哈希值拆成$26$个字母的位权

即$hash(S) = \sum\limits_{a} a * \sum w^i * [s[i] == a]$

通过记录每个字母第一次出现的位置,用$26$的时间来确定$f$是什么

然后通过确定的$f$计算出$f$是正确的时候的$hash$值,和原串的$hash$值比较

复杂度$O(26n)$

自然取模....

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <iostream>
  4. #include <algorithm>
  5. namespace remoon {
  6. #define ri register int
  7. #define ll long long
  8. #define ull unsigned long long
  9. #define rep(io, st, ed) for(ri io = st; io <= ed; io ++)
  10. #define drep(io, ed, st) for(ri io = ed; io >= st; io --)
  11. }
  12. using namespace std;
  13. using namespace remoon;
  14.  
  15. #define sid 500050
  16. char s[], t[sid];
  17.  
  18. int n, m, tim, f[];
  19. int num[], vis[], nxt[], tot;
  20. ull val[], wei[sid];
  21. ull seed = ;
  22.  
  23. inline void Init() {
  24. wei[] = ;
  25. rep(i, , m) wei[i] = wei[i - ] * seed;
  26. rep(i, , m) {
  27. int le = t[i];
  28. if(!vis[le]) nxt[++ tot] = i, vis[le] = ;
  29. val[le] += wei[m - i];
  30. }
  31. tim ++;
  32. }
  33.  
  34. inline void Solve() {
  35. ull now = , tval = ;
  36. rep(i, , m) now += s[i] * wei[m - i];
  37. rep(i, m, n) {
  38.  
  39. tim ++;
  40. int flag = ;
  41.  
  42. rep(j, , tot) {
  43. int v = s[i - m + nxt[j]];
  44. if(vis[v] == tim) { flag = ; break; }
  45. if(vis[v] != tim) vis[v] = tim;
  46. f[j] = v;
  47. }
  48.  
  49. if(!flag) {
  50. tval = ;
  51. rep(j, , tot)
  52. tval += f[j] * val[t[nxt[j]]];
  53. if(tval == now) write(i - m + );
  54. }
  55.  
  56. now -= s[i - m + ] * wei[m - ];
  57. now *= seed; now += s[i + ];
  58. }
  59. }
  60.  
  61. int main() {
  62. scanf("%s", s + ); n = strlen(s + );
  63. scanf("%s", t + ); m = strlen(t + );
  64. Init(); Solve();
  65. return ;
  66. }

现在我明白了$KMP$是非常伟大的算法....

对于此题而言,考虑每个字符的上一个字符离当前字符的距离,这可以成为一个新串

然后比对新串即可

特别的,如果上一个字符出现的位置超过了匹配长度,那么我们也要视作合法

但是,我们发现这种匹配满足有前效性,没有后效性,因此可以用$KMP$

复杂度$O(n)$,十分的优秀

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <iostream>
  4. #include <algorithm>
  5. namespace remoon {
  6. #define ri register int
  7. #define rep(io, st, ed) for(ri io = st; io <= ed; io ++)
  8. #define drep(io, ed, st) for(ri io = ed; io >= st; io --)
  9. }
  10. using namespace std;
  11. using namespace remoon;
  12.  
  13. const int sid = ;
  14.  
  15. int n, m;
  16. char s[sid], t[sid];
  17. int lst[], S[sid], T[sid], nxt[sid];
  18.  
  19. inline bool match(int x, int y) {
  20. if(y > m) return ;
  21. if(x == T[y]) return ;
  22. if(!T[y] && x >= y) return ;
  23. return ;
  24. }
  25.  
  26. int main() {
  27. scanf("%s", s + ); scanf("%s", t + );
  28. n = strlen(s + ); m = strlen(t + );
  29.  
  30. rep(i, , n) {
  31. S[i] = lst[s[i]] ? i - lst[s[i]] : ;
  32. lst[s[i]] = i;
  33. }
  34.  
  35. memset(lst, , sizeof(lst));
  36. rep(i, , m) {
  37. T[i] = lst[t[i]] ? i - lst[t[i]] : ;
  38. lst[t[i]] = i;
  39. }
  40.  
  41. for(ri i = , j = ; i <= m; i ++) {
  42. while(j && !match(T[i], j + )) j = nxt[j];
  43. if(match(T[i], j + )) j ++;
  44. nxt[i] = j;
  45. }
  46.  
  47. for(ri i = , j = ; i <= n; i ++) {
  48. while(j && !match(S[i], j + )) j = nxt[j];
  49. if(match(S[i], j + )) j ++;
  50. if(j == m) printf("%d\n", i - m + );
  51. }
  52. return ;
  53. }

bzoj4641 基因改造 KMP / hash的更多相关文章

  1. BZOJ4641 基因改造[KMP]

    这道题以前好像模拟的时候做过,当时不会做,于是用hash水过去了.. 正解是KMP,还是用当前字符与上一次相同字符位置的距离表示数组,于是数值相等时就代表相似.第一次出现用INF代替. 然后要匹配有多 ...

  2. 【BZOJ4641】基因改造 KMP

    [BZOJ4641]基因改造 Description "人类智慧的冰峰,只有萌萌哒的我寂寞地守望." --TB TB正走在改造人类智慧基因的路上.TB发现人类智慧基因一点也不萌萌哒 ...

  3. Codeforces 1090J $kmp+hash+$二分

    题意 给出两个字符串\(s\)和\(t\),设\(S\)为\(s\)的任意一个非空前缀,\(T\)为\(t\)的任意一个非空前缀,问\(S+T\)有多少种不同的可能. Solution 看了一圈,感觉 ...

  4. 【bzoj4641】基因改造 特殊匹配条件的KMP

    题目描述 如果两个长度相等的字符串,如果存在一种字符的一一映射,使得第一个字符串的所有字符经过映射后与第二个字符串相同,那么就称它们“匹配”.现在给出两个串,求第一个字符串所有长度等于第二个字符串的长 ...

  5. 【BZOJ3940】【BZOJ3942】[Usaco2015 Feb]Censoring AC自动机/KMP/hash+栈

    [BZOJ3942][Usaco2015 Feb]Censoring Description Farmer John has purchased a subscription to Good Hoov ...

  6. 【POJ2185】【KMP + HASH】Milking Grid

    Description Every morning when they are milked, the Farmer John's cows form a rectangular grid that ...

  7. HDU 5782 Cycle(KMP+Hash)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5782 [题目大意] 给出两个字符串,判断他们每一个前缀是否循环同构,循环同构的意思就是,字符串首位 ...

  8. Cycle (KMP + hash)

    题意:给你2个串,让你判断2个字符串的前缀是否满足首尾连接形成的环是不是一样的. 思路:我们需要提前知道的是满足条件的前缀一定满足 strA = str1 + str2, strB = str2 + ...

  9. 7.26机房报零赛——无尽的矩阵【kmp+hash】

    恩,其实大家都没有报零,反正我是蒟蒻 为了纪念我第一次打过哈希,特此写一篇题解 题目描述 从前有一个的小矩阵,矩阵的每个元素是一个字母(区分大小写),突然有一天它发生了 变异,覆盖了整个二维空间,即不 ...

随机推荐

  1. MongoDB警告信息

    更多内容推荐微信公众号,欢迎关注: MongoDB警告信息: 1. WARNING: Using the XFS filesystem is strongly recommended with the ...

  2. lucene总结——(十七)

    (01)rownum和rowid有何区别?      rownum在表结构中是看不见的,只能在select中明确写出rownum方可显示      rownum与不同的表绑定在一起,每张表都有自已的r ...

  3. Once you eliminate all the other factors,the only thing remaining must be the truth.

    Once you eliminate all the other factors,the only thing remaining must be the truth. 一旦你排除了杂因,剩下的一定是 ...

  4. 音频自动增益 与 静音检测 算法 附完整C代码【转】

    转自:https://www.cnblogs.com/cpuimage/p/8908551.html 前面分享过一个算法<音频增益响度分析 ReplayGain 附完整C代码示例> 主要用 ...

  5. C/C++杂记:NULL与0的区别、nullptr的来历

    某些时候,我们需要将指针赋值为空指针,以防止野指针.   有人喜欢使用NULL作为空指针常量使用,例如:int* p = NULL;. 也有人直接使用0值作为空指针常量,例如:int* p = 0;. ...

  6. 读书笔记 effective c++ Item 48 了解模板元编程

    1. TMP是什么? 模板元编程(template metaprogramming TMP)是实现基于模板的C++程序的过程,它能够在编译期执行.你可以想一想:一个模板元程序是用C++实现的并且可以在 ...

  7. liunx系统top命令详解

    ps: 1.按1可以进行 CPU各个和总CPU汇总的切换2.cpu0是最关键的,总控管理各个CPU 3.默认情况下仅显示比较重要的 PID.USER.PR.NI.VIRT.RES.SHR.S.%CPU ...

  8. java基础69 JavaScript产生伪验证码(网页知识)

    1.伪验证码 <!doctype html> //软件版本:DW2018版 <html> <head> <meta charset="utf-8&q ...

  9. Ad Hoc Distributed Queries的启用与关闭

    启用Ad Hoc Distributed Queries: exec sp_configure 'show advanced options',1 reconfigure exec sp_config ...

  10. R语言学习笔记:使用reshape2包实现整合与重构

    R语言中提供了许多用来整合和重塑数据的强大方法. 整合 aggregate 重塑 reshape 在整合数据时,往往将多组观测值替换为根据这些观测计算的描述统计量. 在重塑数据时,则会通过修改数据的结 ...