字符串hash
往往的是暴力分
当然写的好的话运气不是很差的话说不定能AK
O(n) 预处理 O(1)匹配
对于一个长度是n的字符串
设字符集大小为m,默认字符串的长度是s[1...n];
预处理出p[a] = p^a;
那么我们可以计算前缀的hash值
hsh[1] = s[1] * p[1];
hsh[2] = s[2] * p[2] + hsh[1];
hsh[i] = s[i] * p[i] + hsh[i-1];
那么怎么查询子串l.....r
- gethsh(l,r) = hsh[r] - hsh[l-1] * p[l - r + 1]
高中数学就可以推出,这里我就不说了
一般的我们认为子串的hsh值相等那么这两个子串就相等
显然的会有一定的出错概率
而且hash的数会溢出
自然溢出是不太好的
建议对他取模
好,以上是科学,下面讲玄学
对于p的取法 只要是大于M的一个素数就好
比如我常用的233
对于模数
某老师曾说过,需要一个妹子的生日作为模数
因此他从来没有被卡掉过
但是我的妹子的生日显然的不是一个素数
没关系卡掉就卡掉吧我也不在乎
事实上我也没有被卡掉过几次
总之
学习科学使用玄学
bzoj3555一道经典的hash题
很暴力的一道题
枚举每一位,计算去掉该位后的hsh值
边放边统计
#include<iostream>
#include<algorithm>
#include<cstdio>
const int N = 30030;
#define ll unsigned long long
const int M = 20010520;
using namespace std;
int n,l,m;
ll k[N];
struct str{
char s[210];
ll f[210],g[210];
inline void init(){
scanf("%s",s+1);
for(int i = 1;i <= l;i++){
f[i] = f[i - 1] * 233 % M + s[i];
}
for(int i = l;i >= 1;i--){
g[i] = g[i+1] * 233 % M + s[i];
}
}
inline ll hashdel(int x){
return f[x-1] * 233 % M + g[x+1] *233 %M
}
}a[N];
int main(){
cin>>n>>l>>m;
for(int i = 1;i <= n;i++){
a[i].init();
}
int ans = 0;
for(int p = 1;p <= l;p++){
for(int i = 1;i <= n;i++){
k[i] = a[i].hashdel(p);
}
sort(k+1,k+1+n);
int t = 1;
for(int i = 2;i <= n;i++){
if(k[i] == k[i-1]){
ans = ans + t;
t++;
}
else{
t = 1;
}
}
}
cout<<ans;
return 0;
}
总之无论是随机数还是hsh在后面加妹子生日会得更多的分的
QAQ不是我说的
往往的是暴力分
当然写的好的话运气不是很差的话说不定能AK
O(n) 预处理 O(1)匹配
对于一个长度是n的字符串
设字符集大小为m,默认字符串的长度是s[1...n];
预处理出p[a] = p^a;
那么我们可以计算前缀的hash值
hsh[1] = s[1] * p[1];
hsh[2] = s[2] * p[2] + hsh[1];
hsh[i] = s[i] * p[i] + hsh[i-1];
那么怎么查询子串l.....r
- gethsh(l,r) = hsh[r] - hsh[l-1] * p[l - r + 1]
高中数学就可以推出,这里我就不说了
一般的我们认为子串的hsh值相等那么这两个子串就相等
显然的会有一定的出错概率
而且hash的数会溢出
自然溢出是不太好的
建议对他取模
好,以上是科学,下面讲玄学
对于p的取法 只要是大于M的一个素数就好
比如我常用的233
对于模数
某老师曾说过,需要一个妹子的生日作为模数
因此他从来没有被卡掉过
但是我的妹子的生日显然的不是一个素数
没关系卡掉就卡掉吧我也不在乎
事实上我也没有被卡掉过几次
总之
学习科学使用玄学
bzoj3555一道经典的hash题
很暴力的一道题
枚举每一位,计算去掉该位后的hsh值
边放边统计
#include<iostream>
#include<algorithm>
#include<cstdio>
const int N = 30030;
#define ll unsigned long long
const int M = 20010520;
using namespace std;
int n,l,m;
ll k[N];
struct str{
char s[210];
ll f[210],g[210];
inline void init(){
scanf("%s",s+1);
for(int i = 1;i <= l;i++){
f[i] = f[i - 1] * 233 % M + s[i];
}
for(int i = l;i >= 1;i--){
g[i] = g[i+1] * 233 % M + s[i];
}
}
inline ll hashdel(int x){
return f[x-1] * 233 % M + g[x+1] *233 %M
}
}a[N];
int main(){
cin>>n>>l>>m;
for(int i = 1;i <= n;i++){
a[i].init();
}
int ans = 0;
for(int p = 1;p <= l;p++){
for(int i = 1;i <= n;i++){
k[i] = a[i].hashdel(p);
}
sort(k+1,k+1+n);
int t = 1;
for(int i = 2;i <= n;i++){
if(k[i] == k[i-1]){
ans = ans + t;
t++;
}
else{
t = 1;
}
}
}
cout<<ans;
return 0;
}
总之无论是随机数还是hsh在后面加妹子生日会得更多的分的
QAQ不是我说的