写这篇博客仅是为了凑齐神龙,真想学Hash请另寻高明.
真的不想再用文字来叙述这个东西了
给出两个仅含大写字母的字符串s1,s2,求s1在s2中出现了多少次.
unsigned long long power[MAXN],sum[MAXN];
//unsigned long long
char s1[MAXN],s2[MAXN];
int main(){
power[0]=1;
for(int i=1;i<=MAXN;i++)
power[i]=power[i-1]*b;
//预处理出b^n,b是一个质数(自行赋值).
scanf("%s%s",s1+1,s2+1);
int n=strlen(s1+1),m=strlen(s2+1);
for(int i=1;i<=m;i++)
sum[i]=sum[i-1]*b+s2[i]-‘A‘+1;
//计算主串s2的哈希值
//这是字符串哈希的精髓,好好理解一下
unsigned long long s=0;
for(int i=1;i<=n;i++)
s=s*b+s1[i]-‘A‘+1;
//计算匹配串s1的哈希值
//因为我们要计算的是s1在s2中出现的次数,所以是要拿s1
//整个串的哈希值和s2的部分串的哈希值比较,看是否相等
//这就是为什么本题中s1的哈希值直接用变量s存,而s2的
//哈希值要存在一个数组中
//此外,s1和s2的哈希函数(即哈希值的计算方法)要相同.
int ans=0;
for(int i=0;i<=m-n;i++)
if(s==sum[i+n]-sum[i]*power[n])
ans++;
//枚举s2的长度等于s1的子串的哈希值,如果相等,ans+1
printf("%d\n",ans);
return 0;
}
(该图是在模16意义下的哈希表):
#include<bits/stdc++.h>
using namespace std;
const int p1=47,p2=79,mod1=1e6+3,mod2=1e6+9;
//构造两个哈希函数,只有同时满足两个哈希值相等
//才是相同的字符串,能有效降低哈希冲突的概率.
int n,tot,ans;
int nxt[10005],end[10005],head[mod1+5];
string s[10005];
void insert(int x,int y){
nxt[++tot]=head[x];
head[x]=tot;
end[tot]=y;
}
//将一个字符串通过两个哈希函数得到的两个哈希值
//插入邻接表(哈希表)
//结合上面那个图来看就是把x当做表头
//y当做表头后链表上的值
int query(int x,int y){
for(int i=head[x];i;i=nxt[i]){
if(end[i]==y) return 1;
}
return 0;
}
//到哈希表中查询字符串是否存在过
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
cin>>s[i];
int len=s[i].size();
int sum1=0,sum2=0;
for(int j=0;j<len;j++){
sum1=(sum1*p1+s[i][j])%mod1;
sum2=(sum2*p2+s[i][j])%mod2;
}
//双哈希函数,这里没有让s[i][j]-‘a‘什么的,
//是因为字符串可能小写,可能大写,可能是数字,
//就干脆让它自己强制转换成数字就好了.
if(query(sum1,sum2)==1) ans++;
else insert(sum1,sum2);
}
printf("%d",n-ans);
return 0;
}
原文:https://www.cnblogs.com/PPXppx/p/10333536.html