哈希算法详解

一维字符串哈希

功能:在O(1)时间内查询某个区间的子串是什么(该串的哈希值)等等

实现方法:类似于前缀合,对字符串从前到后进行哈希

void init()
{
    p[0] = 1;
    for(int i = 1; i <= len; i ++) {
        p[i] = p[i-1]*base;
    }
}

void Hash()
{
    has[0] = 0;
    for(int i = 1; i <= len; i ++) {
        has[i] = has[i-1]*base + str[i];
    }
}

查询:查询区间[l, r]内字串的哈希值,has[r] - has[l-1]*p[r-l+1]

uLL get_has(int l, int r)
{
    return has[r] - has[l-1]*p[r-l+1];
}

实现代码:(查询字符串str中s出现的次数)= kmp

const uLL base = 131;
uLL has[100010], p[100010]; //unsigned long long 自动溢出(取模)
char str[100010], s[100010];
int len;

void init()
{
    p[0] = 1;
    for(int i = 1; i <= len+5; i ++) {
        p[i] = p[i-1]*base;
    }
}

void Hash()
{
    has[0] = 0;
    for(int i = 1; i <= len; i ++) {
        has[i] = has[i-1]*base + str[i];
    }
}

uLL get_has(int l, int r)
{
    return has[r] - has[l-1]*p[r-l+1];
}

int main()
{
    init();
    scanf("%s%s", s+1, str+1);
    int len1 = strlen(s+1);
    int len2 = strlen(str+1);
    len = len2;
    Hash();
    uLL hs = 0;
    for(int i = 1; i <= len1; i ++) {
        hs = hs*base + s[i];
    }
    int cnt = 0;
    for(int i = 1; i <= len2-len1+1; i ++) {
        if(hs == get_has(i, i+len1-1)) cnt ++;
    }
    printf("%d\n", cnt);
}

二维矩阵哈希

功能:O(1)时间内查询某个子矩阵的是什么(该矩阵的哈希值)

实现方法:类似于二维前缀合,先对每一列进行哈希,然后再对每一行进行哈希

const uLL base1 = 131;
const uLL base2 = 233;

int n, m;
char mp[510][510];
uLL has[510][510];
uLL p1[510], p2[510];

void init()
{
    p1[0] = p2[0] = 1;
    for(int i = 1; i <= 505; i ++) {
        p1[i] = p1[i-1]*base1;
        p2[i] = p2[i-1]*base2;
    }
}

void Hash()
{
    has[0][0] = 0;
    has[0][1] = 0;
    has[1][0] = 0;
    for(int i = 1; i <= n; i ++) { //对列进行哈希
        for(int j = 1; j <= m; j ++) {
            has[i][j] = has[i][j-1]*base1 + mp[i][j] - 'a';
        }
    }
    for(int i = 1; i <= n; i++) {
        for(int j = 1; j <= m; j ++) { //对行进行哈希
            has[i][j] = has[i-1][j]*base2 + has[i][j];
        }
    }
}

查询:查询某个x*y的子矩阵(相同方法先处理出hs[x][y]的值)在原矩阵中出现了多少次

int check(int x , int y)
{
    int cnt = 0;
    for(int i = x; i <= n; i ++) {
        for(int j = y; j <= m; j ++) {
            uLL k = has[i][j] - has[i-x][j]*p2[x] - has[i][j-y]*p1[y] + has[i-x][j-y]*p1[y]*p2[x];
            if(k == hs[nn][mm]) cnt ++;
        }
    }
    return cnt;
}

 

### Python 中哈希算法的详细原理 哈希算法是一种将任意长度的数据映射为固定长度输出的技术,广泛用于数据结构、加密以及数据校验等领域[^1]。在 Python 中,哈希函数的核心作用是对对象生成唯一的数值表示形式。 #### 哈希算法的基本原理 哈希算法的主要目标是通过特定的数学运算,将输入数据转化为一个固定的数值或字符串输出。这一过程具有以下几个特性: - **确定性**:相同的输入总是会产生相同的输出。 - **高效性**:无论输入数据的大小如何,计算哈希值的时间复杂度应接近常数时间 O(1)。 - **均匀分布**:不同的输入应该尽可能产生不重复的输出,减少冲突的可能性。 - **不可逆性**(对于密码学安全的哈希):无法从哈希值反推出原始输入数据。 Python 的内置 `hash()` 函数可以为大多数类型的对象生成哈希值,但它并不适用于所有的场景,尤其是当需要更复杂的哈希功能时,比如安全性更高的哈希或者自定义哈希逻辑。 --- ### Python 中哈希算法的具体实现方式 以下是几种常见的哈希算法及其在 Python 中的应用: #### 1. 内置哈希函数 (`hash`) Python 提供了一个简单易用的内置函数 `hash()`,它可以为任何支持哈希的对象生成一个整型哈希值。例如: ```python print(hash("hello")) # 输出可能因运行环境而异 print(hash(("tuple", "example"))) ``` 需要注意的是,`hash()` 对于某些类型(如浮点数)可能会因为精度损失而导致意外的结果。此外,在不同版本的 Python 或者同一程序的不同运行过程中,`hash()` 的返回值可能是变化的。 --- #### 2. 使用标准库模块 `hashlib` 为了满足更高层次的安全需求,Python 提供了 `hashlib` 模块,它实现了多种流行的哈希算法,包括 MD5、SHA 系列等。这些算法主要用于数据完整性验证和密码存储等方面。 ##### SHA-256 示例 以下是一个基于 `hashlib` 的 SHA-256 加密示例: ```python import hashlib data = b"Secure data to be hashed" sha256_hash = hashlib.sha256(data).hexdigest() print(f"SHA-256 Hash: {sha256_hash}") ``` 该代码片段展示了如何利用 `hashlib` 来创建一个 SHA-256 哈希值,并将其转换为十六进制字符串格式。 --- #### 3. 自定义哈希表实现 如果希望构建自己的哈希表,则可以通过设计合适的散列函数来管理键值对之间的关系。这里给出一个简单的例子作为参考[^3]: ```python class SimpleHashTable: def __init__(self, size=10): self.size = size self.table = [[] for _ in range(size)] def _hash_function(self, key): return sum(ord(c) for c in str(key)) % self.size def insert(self, key, value): index = self._hash_function(key) bucket = self.table[index] for i, (k, v) in enumerate(bucket): if k == key: bucket[i] = (key, value) # 更新已有条目 break else: bucket.append((key, value)) def search(self, key): index = self._hash_function(key) bucket = self.table[index] for k, v in bucket: if k == key: return v raise KeyError(f"Key '{key}' not found") # 测试 ht = SimpleHashTable() ht.insert("name", "Alice") ht.insert("age", 25) print(ht.search("name")) # 输出 Alice print(ht.search("age")) # 输出 25 ``` 此代码演示了一种基本的线性探测解决冲突的方法。 --- #### 4. 高级哈希技术——感知哈希 感知哈希(Perceptual Hashing)特别适合处理多媒体文件的内容相似性比较问题。下面是一段关于图像感知哈希的例子[^4]: ```python import cv2 import numpy as np def compute_phash(image_path, hash_size=8): image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE) resized_image = cv2.resize(image, (hash_size, hash_size)) dct_result = cv2.dct(np.float32(resized_image)) dct_reduced = dct_result[:hash_size, :hash_size] mean_value = np.mean(dct_reduced) phash_bits = "".join(["1" if pixel > mean_value else "0" for row in dct_reduced for pixel in row]) return phash_bits def calculate_hamming_distance(phash1, phash2): return sum(bit1 != bit2 for bit1, bit2 in zip(phash1, phash2)) phash_img1 = compute_phash("image1.png") phash_img2 = compute_phash("image2.png") distance = calculate_hamming_distance(phash_img1, phash_img2) print(f"Haming Distance between images: {distance}") ``` 这段脚本能够评估两幅图片间的差异程度。 --- ### 总结 无论是基础的内置函数还是高级的标准库工具,Python 都提供了丰富的手段去操作各种各样的哈希任务。开发者可以根据具体的项目需求选择最恰当的方式实施解决方案。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值