1. 程式人生 > >hash 模板 x

hash 模板 x

預處理 col ace 接下來 return 請求 統計 計算 是什麽

不懂hash是什麽的盆友給出直通車:滴滴滴,開車啦~

如果你看懂了的話:

hash模板來也~

#include <cstdio>
#include <string>
#include <iostream>
#include <algorithm>

using namespace std;

typedef long long LL;

const int N = 1e5 + 6;  //10006
const int D = 131;      //質數 
const int MD = 1e9 + 7; //大質數 

int
n; string s; unsigned long long f[N], g[N]; //g[i]為D的i次方 void prehash(int n) //進行預處理 { // 預處理時,註意到數字可能很大,對一個數 MD 取模 f[0] = s[0];//預處理前綴和(進行強制類型轉) for(int i=1; i<=n; i++) f[i] = (1LL * f[i-1] * D + s[i-1]) % MD; g[0] = 1; //預處理D for(int i=1; i<=n; i++) g[i]
= 1LL * g[i-1] * D % MD; } int hash(int l, int r) //計算區間 [l,r] 的哈希值 { int a = f[r]; int b = 1LL * f[l-1] * g[r-l+1] % MD; return (a - b + MD) % MD; //+MD是為了防止出現負數 } int main() { cin >> s; n = s.length(); prehash(n); while(!cin.eof())//直至按ctrl+z鍵退出! {
int l, r; cin >> l >> r; cout << s.substr(l-1, r-l+1) << ": " << hash(l, r) << endl; //從l-1到r-l+1的字符 } return 0; }

良心推薦洛谷練手題:P3370

【模板】字符串哈希

題目描述

如題,給定N個字符串(第i個字符串長度為Mi,字符串內包含數字、大小寫字母,大小寫敏感),請求出N個字符串中共有多少個不同的字符串。

友情提醒:如果真的想好好練習哈希的話,請自覺,否則請右轉PJ試煉場:)

輸入輸出格式

輸入格式:

第一行包含一個整數N,為字符串的個數。

接下來N行每行包含一個字符串,為所提供的字符串。

輸出格式:

輸出包含一行,包含一個整數,為不同的字符串個數。

輸入輸出樣例

輸入樣例#1:
5
abc
aaaa
abc
abcc
12345
輸出樣例#1:
4

說明

時空限制:1000ms,128M

數據規模:

對於30%的數據:N<=10,Mi≈6,Mmax<=15;

對於70%的數據:N<=1000,Mi≈100,Mmax<=150

對於100%的數據:N<=10000,Mi≈1000,Mmax<=1500

樣例說明:

樣例中第一個字符串(abc)和第三個字符串(abc)是一樣的,所以所提供字符串的集合為{aaaa,abc,abcc,12345},故共計4個不同的字符串。

Tip: 感興趣的話,你們可以先看一看以下三題:

BZOJ3097:http://www.lydsy.com/JudgeOnline/problem.php?id=3097

BZOJ3098:http://www.lydsy.com/JudgeOnline/problem.php?id=3098

BZOJ3099:http://www.lydsy.com/JudgeOnline/problem.php?id=3099

如果你仔細研究過了(或者至少仔細看過AC人數的話),我想你一定會明白字符串哈希的正確姿勢的^_^

思路:

  題解裏面是有很多種方法的,但是我認為能夠搞懂一種就已經很不錯了……所以我給出的思路就是用set來進行統計,set只能夠允許一種數字出現一次,所以我們就可以將給出的字符串的hash值求出來,加入到set裏面,最後直接輸出set裏面有多少數就行啦~

  PS:定義函數的時候不要用"hash"這個名字,在洛谷裏是關鍵字!!!

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cstring>
#include <set>

using namespace std;

typedef unsigned long long ull;
typedef long long LL;
set<ull>ssr;

const int N = 2333;
const int D = 131;     //質數 
const ull MD= 1e9 + 7; //大質數 

LL n,len;
string s;
 
ull f[N];//預處理前綴和 
ull g[N];//預處理 D的i次方 

int yuchuli(int q)
{
    memset(f,0,sizeof(f));
    memset(g,0,sizeof(g));
    f[0]=s[0];
    for(int i=1;i<=q;i++)
        f[i] = (1LL * f[i-1] * D +s[i-1]) % MD;
    g[0]=1;
    for(int i=1;i<=q;i++)
        g[i] = 1LL * g[i-1] * D % MD;
}

int hash(int l,int r)
{
    ull a = f[r];
    ull b = 1LL * f[l-1] *g[r-l+1] % MD;

    return (a - b + MD) % MD;
}

int main()
{
    cin>>n;
    while(n--)
    {
        cin>>s;
        len=s.length();
        yuchuli(len);
        ull qq = hash(1,len);
        ssr.insert(qq);        
    }
    cout<<ssr.size();
    return 0;
}
/*
5
abc
aaaa
abc
abcc
12345
*/

hash 模板 x