【哈希】洛谷P7469 [NOI Online 2021 提高组] 积木小赛(民间数据)
发布日期:2021-05-07 22:47:32 浏览次数:17 分类:精选文章

本文共 1324 字,大约阅读时间需要 4 分钟。

题目


比赛时最初是想到了 O ( n 3 ) O(n^3) O(n3) 的打法, 可是 n < = 3000 n<=3000 n<=3000 我觉得不太行…

然后就想到了hash,随手打了个俩模数就交了…结果洛谷被卡成60,NOIO被卡成70…
在洛谷弄成3模数,再把数组开大点就A了…A了…A了…
也就是枚举串b内的左端点,往后逐位向后与A串匹配(A串匹配不了的就往后跳,直到找到匹配的字母)(这里我作了一点优化)
哈希判断是否重复,最后统计。


代码

#include
#include
#include
#include
#include
using namespace std;string s1, s2;int f[4000][150], p2, p1, n, hash1, hash2, hash3;int b[100010][501];long long ans;int main(){ scanf("%d", &n); cin >> s1 >> s2; s1 = " " + s1; s2 = " " + s2; for(int i = n-1; i; --i){ for(int j = 97; j <= 123; ++j) //预处理。f[i][j]为第i位后第一次出现j字母的位置 f[i][j] = f[i+1][j]; f[i][s1[i+1]] = i+1; } for(int i = 0; i < n; ++i){ //左端点 p2 = i+1; p1 = 1; hash1 = hash2 = hash3 = 0; while(p2 <= n && p1 <= n){ //b串p2位于a串p1位匹配 while(s1[p1] != s2[p2] && p1) p1 = f[p1][s2[p2]]; //a串往后找 b串s2位的 这个字母 if(p1 == 0) break; //没找到字母 hash1 = (hash1 * 131 + s2[p2]) % 100007; //三重哈希 hash2 = (hash2 * 233 + s2[p2]) % 1333331; hash3 = (hash3 * 199 + s2[p2]) % 49999; for(int j = 1; j <= 499; j += 2){ //判断重复(底数开大!) if(b[hash1][j] == 0){ //新出现 b[hash1][j] = hash2; b[hash1][j+1] = hash3; ++ans; //统计答案 break; } if(b[hash1][j] == hash2 && b[hash1][j+1] == hash3) break; } ++p2; ++p1; } } printf("%lld", ans); return 0;}
上一篇:【KMP】Ybt_子串拆分
下一篇:洛谷P7471 [NOI Online 2021 入门组] 切蛋糕(民间数据)

发表评论

最新留言

路过按个爪印,很不错,赞一个!
[***.219.124.196]2025年03月19日 01时25分15秒