https://www.luogu.com.cn/blog/pks-LOVING/zi-fu-chuan-xue-xi-bi-ji-ha-xi-hash-yu-zi-dian-shu-trie
這一篇好棒!!!
轉自 http://www.yhzq-blog.cc/字符串hash總結/
這一篇也好棒!!!ios
據個人理解,Hash就是一個像函數同樣的東西,你放進去一個值,它給你輸出來一個值。輸出的值就是Hash值。通常Hash值會比原來的值更好儲存(更小)或比較。算法
那字符串Hash就很是好理解了。就是把字符串轉換成一個整數的函數。並且要儘可能作到使字符串對應惟一的Hash值。函數
字符串Hash的種類仍是有不少種的,不過在信息學競賽中只會用到一種名爲「BKDR Hash」的字符串Hash算法。spa
它的主要思路是選取恰當的進制,能夠把字符串中的字符當作一個大數字中的每一位數字,不過比較字符串和比較大數字的複雜度並無什麼區別(高精數的比較也是O(n)的),但只要把它對一個數取模,而後認爲取模後的結果相等原數就相等,那麼就能夠在必定的錯誤率的基礎上O(1)進行判斷了。code
那麼咱們選擇什麼進制比較好?blog
首先不要把任意字符對應到數字0,好比假如把a對應到數字0,那麼將不能只從Hash結果上區分ab和b(雖然能夠額外判斷字符串長度,但不把任意字符對應到數字0更加省事且沒有任何反作用),通常而言,把a-z對應到數字1-26比較合適。字符串
關於進制的選擇實際上很是自由,大於全部字符對應的數字的最大值,不要含有模數的質因子(那還模什麼),好比一個字符集是a到z的題目,選擇2七、23三、19260817 都是能夠的。get
模數的選擇(儘可能仍是要選擇質數):string
絕大多數狀況下,不要選擇一個109級別的數,由於這樣隨機數據都會有Hash衝突,根據生日悖論,隨便找上109−−−√個串就有大機率出現至少一對Hash 值相等的串(參見BZOJ 3098 Hash Killer II)。hash
最穩妥的辦法是選擇兩個109級別的質數,只有模這兩個數都相等才判斷相等,但常數略大,代碼相對難寫,目前暫時沒有辦法卡掉這種寫法(除了卡時間讓它超時)(參見BZOJ 3099 Hash Killer III)。
若是能背過或在考場上找出一個1018級別的質數(Miller-Rabin),也相對靠譜,主要用於前一種擔憂會超時,後一種擔憂被卡。
題目描述
如題,給定\(N\)個字符串(第\(i\)個字符串長度爲 \(M_i\),字符串內包含數字、大小寫字母,大小寫敏感),請求出N個字符串中共有多少個不一樣的字符串。
輸入格式
第一行包含一個整數 N,爲字符串的個數。
接下來 N 行每行包含一個字符串,爲所提供的字符串。
輸出格式
輸出包含一行,包含一個整數,爲不一樣的字符串個數。
#include <cstdio> #include <iostream> #include <cstring> #include <algorithm> #define orz cout << "AK IOI" #define ull unsigned long long using namespace std; const ull base = 131; const int prime = 233317; const ull mod = 0x7ffffffff; inline int read() { int x = 0, f = 1; char ch = getchar(); while (ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();} while (ch >= '0' && ch <= '9') {x = x * 10 + ch - '0';ch = getchar();} return x * f; } ull a[15000]; char s[15005]; int n, ans = 1; ull _hash(char s[]) { int len = strlen(s); ull ans = 0; for(int i = 0; i < len; i++) ans = (ans * base + (ull)s[i]) % mod + prime; return ans; } int main() { n = read(); for(int i = 1; i <= n; i++) { scanf("%s", s); a[i] = _hash(s); } sort(a + 1, a + n + 1); for(int i = 1; i < n; i++) { if(a[i] != a[i + 1]) ans++; } printf("%d",ans); return 0; }