ACM暑假集训日记 17.8.9 POJ 2774 字符串 Hash
来源:互联网 发布:国投证券软件下载 编辑:程序博客网 时间:2024/06/05 19:33
十天了,算是把搜索图论专题做完了,下午看了字符串算法的Hash部分,做了个题目,poj上的,正好注册了一个poj账号,准备有空的时候刷点题,先说上午做的题目。
拓扑题,给出几个大小关系,判断是否能推出,或矛盾,或不确定;
HDU Sorting It All Out
不是非要建立拓扑关系,借鉴思想,利用度来判断矛盾或不确定关系。
下午研究了一下Hash算法、
判断两个字符串是否相等,需要O(n)的时间,其中n为较短字符串的长度。对大量字符串,使用Hash来降低平均复杂度,最坏复杂度不会变,但最坏情况不太常见。
对于较短的字符串,可以直接储存Hash值,但是对于较长的字符串,数字会很大,即使使用unsigned long long也没办法存下,更好的方法是储存这个数对某个质数的余数,但是若采用这种方式储存,当余数不等时,原字符串一定不相等。当余数相等时,无法确定,需要对原字符串使用朴素的比较方法,因为不同数对某个数的余数可能是相等的。
对于之所以使用质数来取模,我们假设Hash表的大小为size(也就是用size取模),当size为合数,那么可以写做size=a*n;当Hash的值为Hashnow=b*n时,则取模后
Hashnow=Hashnow mod size
=Hashnow-(Hashnow / size) * size;
=Hashnow-(b/a)* size;
因为a是固定的,那么Hashnow的值就有b种情况,显然更容易出现不确定情况。
Hash算法实现:
pow[0]=1;
for(int i=1;i<=ls;i++)
pow[i]=(pow[i-1]*num)%mod //计算基数的幂次,节约以后的运算时间,num可以看做是进制
hash[0]=0;
for(int i=0;i<ls;i++)
hash[i+1]=(hash[i]*num+s[i])%mod; //计算s的每一个前缀的hash值
//在main函数中,要对数组 pow,hash赋初值
int gethash(int h[],int i,int j) //得到[i,j)区间内的子串Hash值
{
int tmp=(h[j]-h[i]*pow[j-i])%mod;
if(tmp<0)return tmp+mod;
else return tmp;
}
bool equal(char s1[],char s2[],int n) //朴素方法得到长度为n的两个子串是否相等
{
for(int i=0;i<n;i++)
if(s1[k]!=s2[k])return 0;
return 1;
}
做了一个练习题 POJ 2774
看原题
AC代码
#include<iostream>
#include<string.h>
#include<stdio.h>
#include<algorithm>
using namespace std;
const int N=100001;
int ls1,ls2;
char s1[N],s2[N];
unsigned long long hash1[N],hash2[N],pow[N],a[N];
inline unsigned long long gethash(unsigned long long h[],int i,int j)
{
return h[j]-h[i]*pow[j-i];
}
int havesolution(int t)
{
int n=0;
for(int i=t;i<=ls1;i++)
a[n++]=gethash(hash1,i-t,i);
sort(a,a+n); //必须进行排列,binary_search使用前提需要是已排序的
for(int i=t;i<=ls2;i++)
{
unsigned long long w=gethash(hash2,i-t,i);
if(binary_search(a,a+n,w))
return 1;
}
return 0;
}
int main()
{
scanf("%s",s1);
scanf("%s",s2);
ls1=strlen(s1);
ls2=strlen(s2);
int l=0,r=max(ls1,ls2);
pow[0]=1;
for(int i=1;i<=r;i++)
pow[i]=pow[i-1]*27;
hash1[0]=0;
for(int i=0;i<ls1;i++)
hash1[i+1]=(hash1[i]*27+s1[i]-'a'); //应该是可以看做26进制,但是用26提交了一次error了,改成27才对
for(int i=0;i<ls2;i++)
hash2[i+1]=(hash2[i]*27+s2[i]-'a');
while(l!=r)
{
int t=(l+r)/2;
if(havesolution(t+1))l=t+1;
else r=t;
}
printf("%d\n",l);
return 0;
}
- ACM暑假集训日记 17.8.9 POJ 2774 字符串 Hash
- ACM暑假集训日记 17.8.1
- ACM暑假集训日记 17.8.2
- ACM暑假集训日记 17.8.3
- ACM暑假集训日记 17.8.4
- ACM暑假集训日记 17.8.5
- ACM暑假集训日记 17.8.7
- ACM暑假集训日记 17.8.8
- ACM暑假集训日记 17.8.10
- ACM暑假集训日记 17.8.11
- ACM暑假集训日记 17.8.14
- ACM暑假集训日记 17.8.15 树状数组
- ACM暑假集训日记 17.8.16 树状数组
- ACM暑假集训日记 17.8.18 树状数组
- ACM暑假集训日记 17.7.31
- POJ 1330 大一暑假ACM集训
- ACM暑假集训(0)
- ACM暑假集训方法
- 软件测试基础
- 数据结构-布隆过滤器
- POJ
- 素数对猜想
- Parcelable实现数据组件的数据传递
- ACM暑假集训日记 17.8.9 POJ 2774 字符串 Hash
- 前缀、中缀、后缀表达式
- Xamainr.Forms 基础——Behaviors——可重用Behaviors
- 数素数
- BZOJ 3224 洛谷 3369 【模板】普通平衡树(Treap/SBT)
- Shredding Company
- sql语句合集大全(个人总结)
- 2010-2011 ACM-ICPC, NEERC, Southern Subregional Contest E
- Xamarin.Forms 基础——Behavior+EffectBehavior