hash 模板 x
不懂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; //大質數 intn; 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