首页 > 其他分享 >哈希处理字符串匹配

哈希处理字符串匹配

时间:2023-05-29 11:34:17浏览次数:55  
标签:匹配 MAX unsigned long 哈希 字符串 看做


问题 A: 【 哈希和哈希表】子串查找

时间限制: 1 Sec  内存限制: 128 MB
提交: 65  解决: 18
[提交] [状态] [讨论版] [命题人:admin]

题目描述

这是一道模板题。
给定一个字符串A和一个字符串B,求B在A中的出现次数。A和B中的字符均为英语大写字母或小写字母。
A中不同位置出现的B可重叠。

 

输入

输入共两行,分别是字符串A和字符串B。

输出

输出一个整数,表示B在A中的出现次数。

样例输入


zyzyzyz zyz


样例输出


3


提示

1≤A,B的长度≤106,A、B仅包含大小写字母。

[提交][状态]

【哈希与字符串】

对于字符串“521”,也完全可以看做是数字 521,要检查两个数字字符串是不是相同,只需要检测看做数字时是不是相同。若直接字符串比较,时间O(n),若看做数字再比较,时间O(1);

对于字符串“abc”,我们完全可以把a看做1,b看做2.....,不要看做0,避免前导0的影响,对应成一个数字之后,比较时间就从O(n)降到了O(1)!,这就是哈希的魅力啊。这种方式就是把字符串看做一个k进制整数,称为该字符串的哈希值,通过数值比较大小是最快的,但是呢,字符串的长度有时特别长,整型变量难以存储大数,所以我们把它模除M再存储,即我们一般用的哈希值是模除M之后的值。但是这样就不可避免的会有冲突,一定会存在某个哈希值模除M后恰好等于了另一个字符串的哈希值。

对于k和M的选取,大部分文章都强调选择大素数!但是很少给出证明。这里有一篇的观点是尽量大就可以:javascript:void(0) 然后这个知乎回答里好像挺有道理:https://www.zhihu.com/question/20806796/answer/21359160

然后是我个人理解,M越大越好,其次k与M要互质!通过OJ交题,确实是这样才能AC。既然k要与M互质,那直接去素数最好了。有时候可能还会进行除法,就不得不用逆元了,那么M就必须是素数才有逆元。

【分析】

任选一个进制k=97,M=2^64,用unsigned long long 的自然溢出可以完成这个模除。

求出串B的哈希值,然后在A中进行窗口滚动,和每一个长度等于B长度的子串哈希值进行比较,相等的即为字符串相同。

【代码】

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int MAX=1e6+5;

const int base=95;
char a[MAX],b[MAX];
unsigned long long getval(char ch)
{
    if(ch>='a'&&ch<='z')return ch-'a'+1;
    return ch-'A'+27;
}

ull sum[MAX];
int main()
{
    scanf("%s%s",a,b);
    int n=strlen(b),m=strlen(a);
    sum[0]=getval(a[0]);
    for(int i=1;i<m;i++)sum[i]=sum[i-1]*base+getval(a[i]); //前缀值
    ull ha=0,hb=0,f=1;
    for(int i=0;i<n;i++)f=f*base;//当前最大上限
    for(int i=0;i<n;i++)
        ha=(ha*base+getval(b[i]));
    int ans=0;
    for(int i=0;i<m-n+1;i++)
    {
        if(ha==sum[i+n-1]-sum[i-1]*f)ans++;
    }
    printf("%d\n",ans);
    return 0;
}

 

标签:匹配,MAX,unsigned,long,哈希,字符串,看做
From: https://blog.51cto.com/u_16125110/6369246

相关文章

  • MySQL 将 字符串 转为 整数
    1、CAST(eprAStype)1)type为 SIGNEDSELECTCAST("-12"ASSIGNED);效果如下:2)type为UNSIGNEDSELECTCAST("-12"ASUNSIGNED);效果如下:2、CONVERT(expr,type)SELECTCONVERT('123',SIGNED);额外补充1、CAST和CONVERT两个函数中的type取值可以为:SIGNED,UNS......
  • upc 6597: Don't Be a Subsequence (字符串的最短不匹配子序列 dp)
    6597:Don'tBeaSubsequence时间限制:1Sec  内存限制:128MB提交:237  解决:45[提交][状态][讨论版][命题人:admin] 题目描述AsubsequenceofastringSisastringthatcanbeobtainedbydeletingzeroormorecharactersfromSwithoutchangingtheor......
  • upc 6445: 棋盘V (网络流费用流解决匹配问题)
    6445:棋盘V时间限制:1Sec  内存限制:128MB提交:325  解决:31[提交][状态][讨论版][命题人:admin]题目描述有一块棋盘,棋盘的边长为100000,行和列的编号为1到100000。棋盘上有n个特殊格子,任意两个格子的位置都不相同。现在小K要猜哪些格子是特殊格子。她知道所有格子......
  • java8 stream匹配 anyMatch,allMatch,noneMatch
    anyMatch:判断的条件里,任意一个元素成功,返回trueallMatch:判断条件里的元素,所有的都是,返回truenoneMatch:与allMatch相反,判断条件里的元素,所有的都不是,返回truecount方法,跟List接口中的.size()一样,返回的都是这个集合流的元素的长度,不同的是,流是集合的一个高级工厂,中间操作是工厂里......
  • 二进制数据与16进制字符串相互转化方法
    二进制数据转化为16进制字符串(中间加的‘:'还有‘;'是为了查看下标,也可以自行去掉):publicstaticStringbytesToHexString(byte[]src){StringBuilderstringBuilder=newStringBuilder();if(src==null||src.length<=0){returnnull;}for(inti=0;i<src.length;......
  • shell正则匹配捕获引用进行IP匹配
    在服务器上加了一个服务检测机制,用到正则来匹配IP和捕获分组。shell和其他语言一样也可以使用正则分组捕获,不过不能使用$1或1这样的形式来捕获分组,可以通过数组${BASH_REMATCH}来获得,如${BASH_REMATCH[1]},${BASH_REMATCH[N]}简单的测试如下所示:#!/bin/baship="121.0.2.2"if[......
  • linux 中 grep命令匹配空格和制表符
     001、匹配空格[root@PC1test4]#lsa.txt[root@PC1test4]#cata.txt##测试数据1_aabb2_ccdd3_eeff4_gghhkk[root@PC1test4]#sed-nla.txt##显示出空格和制表符1_aabb$2_ccdd$3_eeff$4_gg\thh\tkk$[root@PC1test4]#grep"......
  • 什么是一致性哈希?一致性哈希是如何工作的?如何设计一致性哈希?
    如果你有n个缓存服务器,一个常见的负载均衡方式是使用以下的哈希方法:服务器索引=哈希(键)%N,其中N是服务器池的大小。让我们通过一个例子来说明这是如何工作的。如表5-1所示,我们有4台服务器和8个字符串键及其哈希值。为了获取存储某个键的服务器,我们执行模运算f(键)%4......
  • python Levenshtein—计算字符串相似性
    参考:https://maxbachmann.github.io/Levenshtein/Levenshtein距离,也称编辑距离,是一种字符串度量,用于衡量两个序列之间的差异。通俗地说,两个字符串之间的Levenshtein距离是将一个字符串更改为另一个字符串所需的最小单字符编辑(插入、删除或替换)次数。pythonLevenshtein中包括......
  • hashmap怎么解决哈希冲突问题?红黑树和AVL树有何区别?
    链地址法hashmap是一种基于数组和链表(或红黑树)的数据结构,它可以通过hash函数将任意长度的键映射到一个固定长度的索引,从而实现快速的存取操作。但是,由于hash函数的结果是有限的,而键的数量是无限的,所以可能存在不同的键映射到同一个索引的情况,这就叫做哈希冲突。为了解决哈希冲突,has......