字符串哈希模板C++实现

最近遇到了好几道字符串比较的题目,感觉直接比较还是挺耗时间的,于是想到了哈希,但是又觉得运算的时候可能会把int数据类型爆掉,所以在讨论哈希之前还是总结一下快速幂。

1、Quickpow

这是个模板,我总结了一下网络上的各种写法,比这短的反正我是不会的:

int quickpow(int a,int b,int c) { // return (a^b)%c ---------- 把a的类型声明改成long long也许会更好
    int ret = 1;
    a %= c;
    while(b){
        if(b&1) ret = (ret*a) % c;
        b >>= 1;
        a = (a*a) % c;
    }
    return ret;
}

因为这里用到了分治的思想,所以用递归代码是很容易实现的,但是我并不推荐使用,很容易就TLE了:

int quickpow_2(int a,int b,int c) {
    int ret = 1;
    a %= c;
    ret = (quickpow_2(a,b/2,c) * quickpow_2(a,b/2,c)) %c
    if(b&1){
        ret = (ret * a) % c;
    }
    return ret;
}

2、Hash

重头戏当然就是哈希函数,这里用到了一个大数和一个大质数用来取模,双关键字比较:

void str_hash(char *s,int &d1,int &d2){ //d1,d2为用于比较的关键字 ---------- sys为进制数
    int i,len = strlen(s);
    for(i = 0;i < len;++ i) {
        d1 = (d1 + (s[i]-‘A‘)*quickpow(sys,i,mod1)) % mod1;
        d2 = (d2 + (s[i]-‘A‘)*quickpow(sys,i,mod2)) % mod2;
    }
}

利用进制之间的转化公式,很容易得到我们想要的十进制数,也就是代表该字符串的两个数字。

至于为什么是两个嘛……你会发现只用一个的话,在数据范围比较大的时候容易出现同一个十进制数要表示两个并不相等的字符串,虽然也可以用在哈希表上面挂链表的方式解决,但是对我个人而言是太麻烦了,毕竟咱oier还是不要写太复杂的代码……

3、All

经过上述讨论,就可以写出完整代码了!!!(Ctrl + C党的福利):

#include<cstdio>
#include<algorithm>
#include<cstring>

using namespace std;
typedef long long LL;
const int sys = 26; //假定字符串只含 A ~ Z,即26进制
const int maxn = 3000; //假定字符串长度小于等于100
const int mod1 = 100000007; //一个常用的取模大数
const int mod2 = 299999321; //一个大质数

char a[maxn];
int ha[maxn][2],n;

int quickpow(LL a,int b,int c) { // return (a^b)%c
    int ret = 1;
    a %= c;
    while(b){
        if(b&1) ret = (ret*a) % c;
        b >>= 1;
        a = (a*a) % c;
    }
    return ret;
}

void str_hash(char *s,int &d1,int &d2){ //d1,d2为用于比较的关键字
    int i,len = strlen(s);
    for(i = 0;i < len;++ i) {
        d1 = (d1 + (s[i]-‘A‘)*quickpow(sys,i,mod1)) % mod1;
        d2 = (d2 + (s[i]-‘A‘)*quickpow(sys,i,mod2)) % mod2;
    }
}

int main(){
    scanf("%d",&n);
    for(int i = 1;i <= n;++ i){
        scanf("%s",a);
        str_hash(a,ha[i][0],ha[i][1]); //读入并处理字符串
//注意,这里并没有保存每个字符串,但是实际运用的时候是需要保存的,毕竟还要输出符合条件的字符串
    }
    for(int i = 1;i <= n;++ i){
        printf("%d %d\n",ha[i][0],ha[i][1]); //输出哈希表
    }
    return 0;
}

本文均为原创内容,转载请注明出处。

时间: 2024-12-10 20:47:59

字符串哈希模板C++实现的相关文章

字符串哈希(自然溢出模板)

P3370 [模板]字符串哈希 题目描述 如题,给定N个字符串(第i个字符串长度为Mi,字符串内包含数字.大小写字母,大小写敏感),请求出N个字符串中共有多少个不同的字符串. 输入输出格式 输入格式: 第一行包含一个整数N,为字符串的个数. 接下来N行每行包含一个字符串,为所提供的字符串. 输出格式: 输出包含一行,包含一个整数,为不同的字符串个数. 输入输出样例 输入样例#1: 5 abc aaaa abc abcc 12345 输出样例#1: 4 说明 时空限制:1000ms,128M 数据

洛谷——P3370 【模板】字符串哈希

题目描述 如题,给定N个字符串(第i个字符串长度为Mi,字符串内包含数字.大小写字母,大小写敏感),请求出N个字符串中共有多少个不同的字符串. 友情提醒:如果真的想好好练习哈希的话,请自觉,否则请右转PJ试炼场:) 输入输出格式 输入格式: 第一行包含一个整数N,为字符串的个数. 接下来N行每行包含一个字符串,为所提供的字符串. 输出格式: 输出包含一行,包含一个整数,为不同的字符串个数. 输入输出样例 输入样例#1: 5 abc aaaa abc abcc 12345 输出样例#1: 4 说明

[模板]字符串哈希的简易做法

题目描述 如题,给定N个字符串(第i个字符串长度为Mi,字符串内包含数字.大小写字母,大小写敏感),请求出N个字符串中共有多少个不同的字符串. 友情提醒:如果真的想好好练习哈希的话,请自觉,否则请右转PJ试炼场:) 输入输出格式 输入格式: 第一行包含一个整数N,为字符串的个数. 接下来N行每行包含一个字符串,为所提供的字符串. 输出格式: 输出包含一行,包含一个整数,为不同的字符串个数. 输入输出样例 输入样例#1: 5 abc aaaa abc abcc 12345 输出样例#1: 4 说明

洛谷 P3370 【模板】字符串哈希

题目描述 如题,给定N个字符串(第i个字符串长度为Mi,字符串内包含数字.大小写字母,大小写敏感),请求出N个字符串中共有多少个不同的字符串. 友情提醒:如果真的想好好练习哈希的话,请自觉,否则请右转PJ试炼场:) 输入输出格式 输入格式: 第一行包含一个整数N,为字符串的个数. 接下来N行每行包含一个字符串,为所提供的字符串. 输出格式: 输出包含一行,包含一个整数,为不同的字符串个数. 输入输出样例 输入样例#1: 5 abc aaaa abc abcc 12345 输出样例#1: 4 说明

luogu P3370 【模板】字符串哈希

题目描述 如题,给定N个字符串(第i个字符串长度为Mi,字符串内包含数字.大小写字母,大小写敏感),请求出N个字符串中共有多少个不同的字符串. 友情提醒:如果真的想好好练习哈希的话,请自觉,否则请右转PJ试炼场:) 输入输出格式 输入格式: 第一行包含一个整数N,为字符串的个数. 接下来N行每行包含一个字符串,为所提供的字符串. 输出格式: 输出包含一行,包含一个整数,为不同的字符串个数. 输入输出样例 输入样例#1: 5 abc aaaa abc abcc 12345 输出样例#1: 4 说明

luoguP3370 【模板】字符串哈希 [hash]

题目描述 如题,给定N个字符串(第i个字符串长度为Mi,字符串内包含数字.大小写字母,大小写敏感),请求出N个字符串中共有多少个不同的字符串. 友情提醒:如果真的想好好练习哈希的话,请自觉,否则请右转PJ试炼场:) 输入输出格式 输入格式: 第一行包含一个整数N,为字符串的个数. 接下来N行每行包含一个字符串,为所提供的字符串. 输出格式: 输出包含一行,包含一个整数,为不同的字符串个数. 输入输出样例 输入样例#1: 5 abc aaaa abc abcc 12345 输出样例#1: 4 说明

#计算回文字符串最大长度模板题

计算回文字符串最大长度模板题 如果一个字符串正着读和倒着读是一样的,则称它是回文的. 给定一个长度为N的字符串S,求他的最长回文子串的长度是多少. 输入格式 输入将包含最多30个测试用例,每个测试用例占一行,以最多1000000个小写字符的形式给出. 输入以一个以字符串"END"(不包括引号)开头的行表示输入终止. 输出格式 对于输入中的每个测试用例,输出测试用例编号和最大回文子串的长度(参考样例格式). 每个输出占一行. 输入样例: abcbabcbabcba abacacbaaaa

UvaLive 6439 Pasti Pas! 字符串哈希

链接:http://vjudge.net/problem/viewProblem.action?id=47586 题意:给一个字符串,可以将从前数第i~j和从后数第i~j字符串看作一个字符,问整段字符串看作一个回文里有多少个字符. 思路:字符串哈希,从前开始哈希也从后开始哈希,遇到哈希值相同就多两个字符,最后处理一下中间的字符即可. 代码: #include <iostream> #include <cstdio> #include <cstring> #include

HDU 4821 杭州现场赛:每个片段字符串哈希比较

I - String Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Practice HDU 4821 Description Given a string S and two integers L and M, we consider a substring of S as "recoverable" if and only if (i) I