首页 > 编程语言 >KMP&&哈希算法

KMP&&哈希算法

时间:2024-04-02 20:31:22浏览次数:34  
标签:aba Hash 哈希 int next && KMP 字符串 arr1

KMP算法

KMP算法是一种字符串匹配算法,用于匹配模式串P在文本串S中出现的所有位置。

例如S=“ababac”,P="aba",那么出现的所有位置是1 3

KMP算法将原本O(n^2)的字符串匹配算法优化到了O(n),其精髓在于next数组,next数组表示此时模式串下标失配时应该移动到的位置,(每次下标失配时,就是i!=j了,j=next[j-1])也表示最长的相同真前后缀的长度。

字符串“aba”这个例子来说的话,前缀(从左往右数)有:a,ab,aba(因为aba与原字符相等,所以不是真前缀)后缀(从右往左):a,ba,aba

字符串aba 

a的真前缀真后缀为0  ab的真前缀为a真后缀为b,所以也为0  aba的最长真前缀真后缀为a(长度设为1)所以aba的真前缀真后缀为1

字符串ababac

abab 的真前缀为 a,ab,aba真后缀有b,ab,bab所以最长真前后缀为ab,即为2

ababa 的真前缀有 a,ab,aba,abab,真后缀有a,ba,aba,baba,所以最长真前后缀为aba,即为3

计算next数组(next数组仅与模式串P有关)的方式就是P自己去匹配自己

KMP算法模板

int[] next=new int[p.length];
next[0]=0;
for(in i=1,j=0;i<p.length;i++){

    while(j>0&&p[j]!=p[i]){
        j=next[j-1];//不断匹配i,j直到p[i]==p[j]或者j==0
    }
    if(p[i]==p[j]){
        j++;
         next[i]=j;
    }
   
}

通过next数组进行匹配

for(int i=0,j=0;i<n;i++){

    while(j>0&&s[i]!=p[j])j=next[j-1];
    if(s[i]==p[j])j++;
    if(j==m)//匹配成功一次
}    

 字符串Hash算法

(基于进制的)字符串Hash本质上时一个用数字表示一段字符串,从而降低字符串处理的复杂度。

这个数字是一个很大的数字,采用long类型,还需要一个进制数base,用于规定这个数字的进制

Hash数组h[i]表示字符串s[1~i]的Hash值,采用类似前缀和的形式以便求出任意一个字串的Hash值。

(字符串转化成为数字)

字符串Hash初始化

long base=131;//base一般为一个质数(进制数)

long h[N];//h[i]表示s[1~i]的Hash(类似前缀和)

char s[N];//我们的字符串

for(int i=1;i<=n;++i) h[i]=h[i-1]*base+s[i]-'A'+1;//s[i]-‘A’+1表示字符串在我们字母表中的位置

获取字串s[1]~s[r]的Hash

long getHash(int l,int r){

        return  h[r]-h[l-1]*b[r-l+1];//b[i]表示base的i次方(预处理)

}

  例题实战

斤斤计较的小 Z

题目描述

小 Z 同学没天都喜欢斤斤计较,今天他又跟字符串杠起来了。

他看到了两个字符串 S1 S2 ,他想知道 S1 在 S2 中出现了多少次。

现在给出两个串 S1,S2(只有大写字母),求 S1 在 S2 中出现了多少次。

输入描述

共输入两行,第一行为 S1,第二行为 S2。

输出描述

输出一个整数,表示 S1 在 S2 中出现了多少次。

输入输出样例

示例1

输入

LQYK
LQYK

输出

1

 代码

kmp实现
​

public class jinjinjijiao {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner scan=new Scanner(System.in);
		char[] arr1=scan.next().toCharArray();
		char[] arr2=scan.next().toCharArray();
		int len1=arr1.length;
		int len2=arr2.length;
		int[] next=new int[len1];
		for(int i=1,j=0;i<len1;i++) {
			while(j>0&&arr1[i]!=arr1[j]) {
				j=next[j-1];
			}
			if(arr1[i]==arr1[j]) {
				j++;
			}
			next[i]=j;
		}
		int ans=0;
		for(int i=0,j=0;i<len2;i++) {
			while(j>0&&arr1[j]!=arr2[i]) {
				j=next[j-1];
			}
			if(arr1[j]==arr2[i]) {
				j++;
			}
			if(j==len1) {
				ans++;
				j=0;
			}
			
		}
		System.out.println(ans);
	}

}

​
Hash实现
package shiti;
import java.util.*;
public class Hash {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner scan=new Scanner(System.in);
		char[] arr1=scan.next().toCharArray();
		char[] arr2=scan.next().toCharArray();
		int m=arr1.length;
		int n=arr1.length;
		long[] h=new long[n+1];
		long[] s=new long[n+1];
		long res=0;
		long base=131;
		for(int i=0;i<m;i++) {//先求arr1的hash值
			res=res*base+(arr1[i]-'A'+1);
		}
		s[0]=1;
		for(int i=1;i<=n;i++) {
			h[i]=h[i-1]*base+(arr2[i-1]-'A'+1);
			s[i]=s[i-1]*base;
			
		}
		int ans=0;
		for(int i=1;i+m-1<=n;i++) {
		long sum=h[i+m-1]-h[i-1]*s[m];
			if(sum==res)
				ans++;
		}
		
		System.out.println(ans);
	}

}

标签:aba,Hash,哈希,int,next,&&,KMP,字符串,arr1
From: https://blog.csdn.net/weixin_62944148/article/details/137204526

相关文章

  • kmp板子
    书上讲的感觉不好理解,不如算法竞赛上分析的题目链接:https://www.luogu.com.cn/problem/P3375贴板子:#include<iostream>#include<vector>#include<algorithm>#include<math.h>#include<sstream>#include<string>#include<string.h>#include<i......
  • 线性探索哈希表
    线性探索哈希表基础操作实现:#include<iostream>usingnamespacestd;enumState{ STATE_UNUSE,//neverused STATE_USING,//isusing STATE_DEL,//onceused};//桶的类型structBucket{ Bucket(intkey=0,Statestate=STATE_UNUSE) :_key(key), _st......
  • Python数据结构与算法——数据结构(链表、哈希表、树)
    目录链表  链表介绍  创建和遍历链表  链表节点插入和删除  双链表  链表总结——复杂度分析哈希表(散列表)哈希表介绍哈希冲突哈希表实现哈希表应用树树树的示例——模拟文件系统二叉树二叉树的链式存储 二叉树的遍历二叉搜索树插入......
  • 树哈希
    这种东西看代码比说话好用。#include<bits/stdc++.h>#defineintlonglong#defineullunsigned#defineup(i,l,r)for(inti=l;i<=r;++i)#definedn(i,r,l)for(inti=r;i>=l;--i)#definepbpush_backusingnamespacestd;constintN=111;constullmask=st......
  • LeetCode Hot100-哈希-两数之和
    题目描述:给定一个整数数组nums和一个整数目标值target,请你在该数组中找出和为目标值target的两个整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。你可以按任意顺序返回答案。示例1:输入:nums=[2,7,1......
  • 使用OpenEuler x86_64 实现Bouncycastle SM3哈希功能
    使用OpenEulerx86_64实现BouncycastleSM3哈希功能一、安装运行环境安装java和mavensudoyuminstalljava-17-openjdksudoyuminstallmaven安装完成后,你就可以在OpenEuler上使用Maven来管理Java项目了。二、创建项目工程在项目根目录下创建pom.xml文件......
  • KMP算法
    一.概述要解决的问题:字符串匹配问题。目标串target:"aabaabaafa"模式串pattern:"aabaaf"传统算法:双层for循环遍历目标串target和模式串pattern,判断pattern在target第一次出现的位置。时间复杂度为:\(O(pattern.size()*target.size())\)=\(O(m*n)\)KMP算法核心思路:在对目标......
  • KMP
    PMT:部分匹配表(PartialMatchTable)表示含义:t[0,i]的前后缀最大匹配长度s=input()t=input()n,m=len(s),len(t)pmt=[0]*mc=0foriinrange(1,m):x=t[i]whilecandt[c]!=x:c=pmt[c-1]ift[c]==x:c+=1pmt[......
  • 灵茶之KMP01
    灵茶之KMP01题目链接https://codeforces.com/problemset/problem/1137/B题目大意输入两个长度均≤\(5*10^5\)的字符串s和字符串t,只包含'0'和'1'。重排s中的字符,使得s中有尽量多的子串等于t。输出重排后的s。如果有多个答案,输出任意一个。思路贪心的思路......
  • KMP算法
    对于字符串“abababca”,它的next如下表所示:voidget_next(SStringT,int*next){inti=1,j=0;next[1]=0;//next[1]的值总是0while(i<T.length){if(j==0||T.ch[i]==T.ch[j]){//如果j处于0位或者,俩字符相等++i......