1. 程式人生 > >字串雜湊 模板

字串雜湊 模板

模板

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const int maxn=2e4+10;
const int inf=0x7ffffff;
inline int read()
{
	int f=1,num=0;
	char ch=getchar();
	while (!isdigit(ch)) { if (ch=='-') f=-1; ch=getchar(); }
	while (isdigit(ch)) num=(num<<1)+(num<<
3)+(ch^48), ch=getchar(); return num*f; } char s[maxn]; ull a[maxn]; ull base=13331; ull Hash() { int len=strlen(s); ull hash=0; for(int i=0;i<len;i++) hash=hash*base+s[i]; return hash&inf; } int main() { int n=read(); for(int i=0;i<n;i++) { cin>>
s; a[i]=Hash(); } sort(a,a+n); int ans=1; for(int i=1;i<n;i++) if(a[i]!=a[i-1]) ++ans; printf("%d\n",ans); return 0; }

轉自大佬https://blog.csdn.net/qq_38891827/article/details/80723483

//暫時沒用到雙hash,用到會過來補充
//hash一般用來解決字串判重/字串匹配問題
//遇見不定長問題可通過二分+hash降低複雜度
//遇見定長字串問題可通過尺取+hash來降低複雜度
//二維hash的時候尺取方法就是把之前不需要的都變為0再加上當前行, //將匹配字串整體下移,來驗證hash值是否相等 #include<string.h> typedef unsigned long long ull; const int maxn=1e5+5; ull hash_[maxn],xp[maxn]; void init() { xp[0]=1; for(int i=1;i<maxn;i++) xp[i]=xp[i-1]*13331;//這裡13331玄學數字,大概可以隨意換 return ; } void make_hash(char str[])//處理出str的hash值 { int len=strlen(str); hash_[len]=0; for(int i=len-1;i>=0;i--) { hash_[i]=hash_[i+1]*13331+str[i]-'A'+1; } return ; } ull Get_hash(int i,int L)//得到起點為i,長度為L的子串的hash值 { return hash_[i]-hash_[i+L]*xp[L]; }

例題

題目

http://acm.hdu.edu.cn/showproblem.php?pid=1686

程式碼

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const int maxn = 1e6+5;
ull xp[maxn],hash_1[maxn],hash_2[maxn];
void init()
{
    xp[0]=1;
    for(int i=1;i<maxn;i++)
        xp[i]=xp[i-1]*13331;
}
ull get_hash(int i,int L,ull hash_[])//get_hash(i,L)可以得到從位置i開始的,長度為L的子串的hash值.
{
    return hash_[i]-hash_[i+L]*xp[L];
}
int make_hash(char str[],ull hash_[])
{
    int len=strlen(str);
    hash_[len]=0;
    for(int i=len-1;i>=0;i--)
        hash_[i]=hash_[i+1]*13331+(str[i]-'a'+1);
    return len;
}
char str[maxn],str2[maxn];
int main()
{
    init();
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int ans=0;
        scanf("%s%s",str,str2);
        int len1=make_hash(str,hash_1);
        int len2=make_hash(str2,hash_2);
        ull tmp=get_hash(0,len1,hash_1);
        for(int i=0;i<len2-len1+1;i++)//注意列舉時的邊界問題
            if(get_hash(i,len1,hash_2)==tmp)
                ans++;
        printf("%d\n",ans);
    }
    return 0;
}