首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

2023-11-08:用go语言,字符串哈希原理和实现 比如p = 233, 也就是课上说的选择的质数进制 “ 3 1 2 5

2023-11-08:用go语言,字符串哈希原理和实现

比如p = 233, 也就是课上说的选择的质数进制

" 3 1 2 5 6 ..."

hash[0] = 3 * p的0次方

hash[1] = 3 * p的1次方 + 1 * p的0次方

hash[2] = 3 * p的2次方 + 1 * p的1次方 + 2 * p的0次方

hash[3] = 3 * p的3次方 + 1 * p的2次方 + 2 * p的1次方 + 5 * p的0次方

hash[4] = 3 * p的4次方 + 1 * p的3次方 + 2 * p的2次方 + 5 * p的1次方 + 6 * p的0次方

次方是倒过来的,课上讲错了

所以hash[i] = hash[i-1] * p + arr[i],这个方式就可以得到上面说的意思

于是,你想得到子串"56"的哈希值

子串"56"的哈希值 = hash[4] - hash[2]*p的2次方(就是子串"56"的长度次方)

hash[4] = 3 * p的4次方 + 1 * p的3次方 + 2 * p的2次方 + 5 * p的1次方 + 6 * p的0次方

hash[2] = 3 * p的2次方 + 1 * p的1次方 + 2 * p的0次方

hash[2] * p的2次方 = 3 * p的4次方 + 1 * p的3次方 + 2 * p的2次方

所以hash[4] - hash[2] * p的2次方 = 5 * p的1次方 + 6 * p的0次方

这样就得到子串"56"的哈希值了

抱歉,课上讲错了。应该是上面的方式。

所以,子串s[l...r]的哈希值 = hash[r] - hash[l-1] * p的(r-l+1)次方

也就是说,hash[l-1] * p的(r-l+1)次方,正好和hash[r]所代表的信息,前面对齐了

减完之后,正好就是子串s[l...r]的哈希值。

来自左程云。

答案2023-11-08:

go和c++代码用灵捷3.5编写,不需要修改。

大体过程如下:

rightCheck函数的过程:

1.检查l1和l2是否超出字符串边界,如果超出则返回false。

2.如果l1和l2相等,则直接返回true。

3.判断从l1开始长度为length的子串和从l2开始长度为length的子串是否相等,如果相等则返回true,否则返回false。

hashCheck函数的过程:

1.计算l1到r1和l2到r2两个子串的哈希值。

2.检查r1和r2是否超出字符串边界,如果超出则返回false。

3.根据哈希值判断两个子串是否相等,如果相等则返回true,否则返回false。

rightCheck函数的时间复杂度:O(length)

hashCheck函数的时间复杂度:O(1)

rightCheck函数的额外空间复杂度:O(1)

hashCheck函数的额外空间复杂度:O(1)

go完整代码如下:

package?main

import?(

"fmt"

"math/rand"

)

const?MAXN?=?100005

var?pow?[MAXN]int64

var?hash?[MAXN]int64

var?base?=?499

func?rightCheck(str?string,?l1?int,?l2?int,?length?int)?bool?{

if?l1+length?>?len(str)?||?l2+length?>?len(str)?{

return?false

}

if?l1?==?l2?{

return?true

}

return?str[l1:l1+length]?==?str[l2:l2+length]

}

func?build(str?string,?n?int)?{

pow[0]?=?1

for?j?:=?1;?j?

pow[j]?=?pow[j-1]?*?int64(base)

}

hash[0]?=?int64(str[0]-'a')?+?1

for?j?:=?1;?j?

hash[j]?=?hash[j-1]*int64(base)?+?int64(str[j]-'a')?+?1

}

}

func?hashCheck(n,?l1,?l2,?length?int)?bool?{

r1?:=?l1?+?length?-?1

r2?:=?l2?+?length?-?1

if?r1?>=?n?||?r2?>=?n?{

return?false

}

return?hashf(l1,?r1)?==?hashf(l2,?r2)

}

func?hashf(l,?r?int)?int64?{

var?ans?int64

ans?=?hash[r]

if?l?==?0?{

ans?-=?0

}?else?{

ans?-=?hash[l-1]?*?pow[r-l+1]

}

return?ans

}

func?randomString(length,?v?int)?string?{

str?:=?make([]byte,?length)

for?i?:=?0;?i?

str[i]?=?byte('a'?+?(int64(v)*int64(i))%26)

}

return?string(str)

}

func?main()?{

test?:=?"abcabcabcabcabcabcabcabc"

size?:=?len(test)

build(test,?size)

fmt.Println(hashCheck(size,?6,?15,?3))

fmt.Println("测试开始")

N?:=?10000

V?:=?3

testTeams?:=?100

testTimes?:=?5000

LEN?:=?6

for?i?:=?0;?i?

n?:=?(int)(rand.Float64()*float64(N))?+?1

str?:=?randomString(n,?V)

build(str,?n)

for?k?:=?0;?k?

l1?:=?(int)(rand.Float64()?*?float64(n))

l2?:=?(int)(rand.Float64()?*?float64(n))

length?:=?(int)(rand.Float64()*float64(LEN))?+?1

ans1?:=?rightCheck(str,?l1,?l2,?length)

ans2?:=?hashCheck(n,?l1,?l2,?length)

if?ans1?!=?ans2?{

fmt.Println("出错了!")

break

}

}

}

fmt.Println("测试结束")

}

在这里插入图片描述c++完整代码如下:

#include?

#include?

#include?

using?namespace?std;

const?int?MAXN?=?100005;

long?long?pow0[MAXN];

long?long?hashArr[MAXN];

int?base?=?499;

bool?rightCheck(string?str,?int?l1,?int?l2,?int?len)?{

if?(l1?+?len?>?str.length()?||?l2?+?len?>?str.length())?{

return?false;

}

if?(l1?==?l2)?{

return?true;

}

return?str.substr(l1,?len)?==?str.substr(l2,?len);

}

void?build(string?str,?int?n)?{

pow0[0]?=?1;

for?(int?j?=?1;?j?

pow0[j]?=?pow0[j?-?1]?*?base;

}

hashArr[0]?=?str[0]?-?'a'?+?1;

for?(int?j?=?1;?j?

hashArr[j]?=?hashArr[j?-?1]?*?base?+?str[j]?-?'a'?+?1;

}

}

bool?hashCheck(int?n,?int?l1,?int?l2,?int?len)?{

int?r1?=?l1?+?len?-?1;

int?r2?=?l2?+?len?-?1;

if?(r1?>=?n?||?r2?>=?n)?{

return?false;

}

return?hashArr[l1?+?len?-?1]?-?(l1?==?0???0?:?hashArr[l1?-?1]?*?pow0[len])?==?hashArr[l2?+?len?-?1]?-?(l2?==?0???0?:?hashArr[l2?-?1]?*?pow0[len]);

}

string?randomString(int?len,?int?v)?{

string?str;

for?(int?i?=?0;?i?

str?+=?char('a'?+?rand()?%?v);

}

return?str;

}

int?main()?{

string?test?=?"abcabcabcabcabcabcabcabc";

int?size?=?test.length();

build(test,?size);

cout?

cout?

int?N?=?10000;

int?V?=?3;

int?testTeams?=?100;

int?testTimes?=?5000;

int?LEN?=?6;

for?(int?i?=?0;?i?

int?n?=?rand()?%?N?+?1;

string?str?=?randomString(n,?V);

build(str,?n);

for?(int?k?=?0;?k?

int?l1?=?rand()?%?n;

int?l2?=?rand()?%?n;

int?len?=?rand()?%?LEN?+?1;

bool?ans1?=?rightCheck(str,?l1,?l2,?len);

bool?ans2?=?hashCheck(n,?l1,?l2,?len);

if?(ans1?!=?ans2)?{

cout?

break;

}

}

}

cout?

return?0;

}

在这里插入图片描述

  • 发表于:
  • 原文链接https://page.om.qq.com/page/OxPCh-9Sv6bB7O0aJ_EHKYgA0
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

相关快讯

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券
http://www.vxiaotou.com