bzoj4641 基因改造 KMP / hash
依稀记得,$NOIP$之前的我是如此的弱小....
完全不会$KMP$的写法,只会暴力$hash$....
大体思路为把一个串的哈希值拆成$26$个字母的位权
即$hash(S) = \sum\limits_{a} a * \sum w^i * [s[i] == a]$
通过记录每个字母第一次出现的位置,用$26$的时间来确定$f$是什么
然后通过确定的$f$计算出$f$是正确的时候的$hash$值,和原串的$hash$值比较
复杂度$O(26n)$
自然取模....
- #include <cstdio>
- #include <cstring>
- #include <iostream>
- #include <algorithm>
- namespace remoon {
- #define ri register int
- #define ll long long
- #define ull unsigned long long
- #define rep(io, st, ed) for(ri io = st; io <= ed; io ++)
- #define drep(io, ed, st) for(ri io = ed; io >= st; io --)
- }
- using namespace std;
- using namespace remoon;
- #define sid 500050
- char s[], t[sid];
- int n, m, tim, f[];
- int num[], vis[], nxt[], tot;
- ull val[], wei[sid];
- ull seed = ;
- inline void Init() {
- wei[] = ;
- rep(i, , m) wei[i] = wei[i - ] * seed;
- rep(i, , m) {
- int le = t[i];
- if(!vis[le]) nxt[++ tot] = i, vis[le] = ;
- val[le] += wei[m - i];
- }
- tim ++;
- }
- inline void Solve() {
- ull now = , tval = ;
- rep(i, , m) now += s[i] * wei[m - i];
- rep(i, m, n) {
- tim ++;
- int flag = ;
- rep(j, , tot) {
- int v = s[i - m + nxt[j]];
- if(vis[v] == tim) { flag = ; break; }
- if(vis[v] != tim) vis[v] = tim;
- f[j] = v;
- }
- if(!flag) {
- tval = ;
- rep(j, , tot)
- tval += f[j] * val[t[nxt[j]]];
- if(tval == now) write(i - m + );
- }
- now -= s[i - m + ] * wei[m - ];
- now *= seed; now += s[i + ];
- }
- }
- int main() {
- scanf("%s", s + ); n = strlen(s + );
- scanf("%s", t + ); m = strlen(t + );
- Init(); Solve();
- return ;
- }
现在我明白了$KMP$是非常伟大的算法....
对于此题而言,考虑每个字符的上一个字符离当前字符的距离,这可以成为一个新串
然后比对新串即可
特别的,如果上一个字符出现的位置超过了匹配长度,那么我们也要视作合法
但是,我们发现这种匹配满足有前效性,没有后效性,因此可以用$KMP$
复杂度$O(n)$,十分的优秀
- #include <cstdio>
- #include <cstring>
- #include <iostream>
- #include <algorithm>
- namespace remoon {
- #define ri register int
- #define rep(io, st, ed) for(ri io = st; io <= ed; io ++)
- #define drep(io, ed, st) for(ri io = ed; io >= st; io --)
- }
- using namespace std;
- using namespace remoon;
- const int sid = ;
- int n, m;
- char s[sid], t[sid];
- int lst[], S[sid], T[sid], nxt[sid];
- inline bool match(int x, int y) {
- if(y > m) return ;
- if(x == T[y]) return ;
- if(!T[y] && x >= y) return ;
- return ;
- }
- int main() {
- scanf("%s", s + ); scanf("%s", t + );
- n = strlen(s + ); m = strlen(t + );
- rep(i, , n) {
- S[i] = lst[s[i]] ? i - lst[s[i]] : ;
- lst[s[i]] = i;
- }
- memset(lst, , sizeof(lst));
- rep(i, , m) {
- T[i] = lst[t[i]] ? i - lst[t[i]] : ;
- lst[t[i]] = i;
- }
- for(ri i = , j = ; i <= m; i ++) {
- while(j && !match(T[i], j + )) j = nxt[j];
- if(match(T[i], j + )) j ++;
- nxt[i] = j;
- }
- for(ri i = , j = ; i <= n; i ++) {
- while(j && !match(S[i], j + )) j = nxt[j];
- if(match(S[i], j + )) j ++;
- if(j == m) printf("%d\n", i - m + );
- }
- return ;
- }
bzoj4641 基因改造 KMP / hash的更多相关文章
- BZOJ4641 基因改造[KMP]
这道题以前好像模拟的时候做过,当时不会做,于是用hash水过去了.. 正解是KMP,还是用当前字符与上一次相同字符位置的距离表示数组,于是数值相等时就代表相似.第一次出现用INF代替. 然后要匹配有多 ...
- 【BZOJ4641】基因改造 KMP
[BZOJ4641]基因改造 Description "人类智慧的冰峰,只有萌萌哒的我寂寞地守望." --TB TB正走在改造人类智慧基因的路上.TB发现人类智慧基因一点也不萌萌哒 ...
- Codeforces 1090J $kmp+hash+$二分
题意 给出两个字符串\(s\)和\(t\),设\(S\)为\(s\)的任意一个非空前缀,\(T\)为\(t\)的任意一个非空前缀,问\(S+T\)有多少种不同的可能. Solution 看了一圈,感觉 ...
- 【bzoj4641】基因改造 特殊匹配条件的KMP
题目描述 如果两个长度相等的字符串,如果存在一种字符的一一映射,使得第一个字符串的所有字符经过映射后与第二个字符串相同,那么就称它们“匹配”.现在给出两个串,求第一个字符串所有长度等于第二个字符串的长 ...
- 【BZOJ3940】【BZOJ3942】[Usaco2015 Feb]Censoring AC自动机/KMP/hash+栈
[BZOJ3942][Usaco2015 Feb]Censoring Description Farmer John has purchased a subscription to Good Hoov ...
- 【POJ2185】【KMP + HASH】Milking Grid
Description Every morning when they are milked, the Farmer John's cows form a rectangular grid that ...
- HDU 5782 Cycle(KMP+Hash)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5782 [题目大意] 给出两个字符串,判断他们每一个前缀是否循环同构,循环同构的意思就是,字符串首位 ...
- Cycle (KMP + hash)
题意:给你2个串,让你判断2个字符串的前缀是否满足首尾连接形成的环是不是一样的. 思路:我们需要提前知道的是满足条件的前缀一定满足 strA = str1 + str2, strB = str2 + ...
- 7.26机房报零赛——无尽的矩阵【kmp+hash】
恩,其实大家都没有报零,反正我是蒟蒻 为了纪念我第一次打过哈希,特此写一篇题解 题目描述 从前有一个的小矩阵,矩阵的每个元素是一个字母(区分大小写),突然有一天它发生了 变异,覆盖了整个二维空间,即不 ...
随机推荐
- MongoDB警告信息
更多内容推荐微信公众号,欢迎关注: MongoDB警告信息: 1. WARNING: Using the XFS filesystem is strongly recommended with the ...
- lucene总结——(十七)
(01)rownum和rowid有何区别? rownum在表结构中是看不见的,只能在select中明确写出rownum方可显示 rownum与不同的表绑定在一起,每张表都有自已的r ...
- 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. 一旦你排除了杂因,剩下的一定是 ...
- 音频自动增益 与 静音检测 算法 附完整C代码【转】
转自:https://www.cnblogs.com/cpuimage/p/8908551.html 前面分享过一个算法<音频增益响度分析 ReplayGain 附完整C代码示例> 主要用 ...
- C/C++杂记:NULL与0的区别、nullptr的来历
某些时候,我们需要将指针赋值为空指针,以防止野指针. 有人喜欢使用NULL作为空指针常量使用,例如:int* p = NULL;. 也有人直接使用0值作为空指针常量,例如:int* p = 0;. ...
- 读书笔记 effective c++ Item 48 了解模板元编程
1. TMP是什么? 模板元编程(template metaprogramming TMP)是实现基于模板的C++程序的过程,它能够在编译期执行.你可以想一想:一个模板元程序是用C++实现的并且可以在 ...
- liunx系统top命令详解
ps: 1.按1可以进行 CPU各个和总CPU汇总的切换2.cpu0是最关键的,总控管理各个CPU 3.默认情况下仅显示比较重要的 PID.USER.PR.NI.VIRT.RES.SHR.S.%CPU ...
- java基础69 JavaScript产生伪验证码(网页知识)
1.伪验证码 <!doctype html> //软件版本:DW2018版 <html> <head> <meta charset="utf-8&q ...
- Ad Hoc Distributed Queries的启用与关闭
启用Ad Hoc Distributed Queries: exec sp_configure 'show advanced options',1 reconfigure exec sp_config ...
- R语言学习笔记:使用reshape2包实现整合与重构
R语言中提供了许多用来整合和重塑数据的强大方法. 整合 aggregate 重塑 reshape 在整合数据时,往往将多组观测值替换为根据这些观测计算的描述统计量. 在重塑数据时,则会通过修改数据的结 ...