OI 字串 常用雜湊方法

2021-07-23 12:17:13 字數 2344 閱讀 6388

下面這個方法來自 演算法競賽入門經典-訓練指南

方法對於乙個字串s,令h[i] = h[i+1]*x + s[i] ,其中x是你自選的乙個常數。令xp[i] = xp[i-1]*x

這樣之後定義s的起點為下標i,長度為len的子串的雜湊值為 h[i] - h[i+len]*xp[len] 。這個值與子串的位置,子串的內容,還有你自選的常數都有關係。雜湊值使用unsigned long long(如果不是oi,可以使用int128的話當然更好) 不同子串的雜湊值一定不會相同嗎?不一定,但是相同的概率非常非常小。如果覺得不夠保險可以分別選定兩次x常數,雙雜湊來做。

應用dp超時,字尾陣列re了?(orz fmuckss神犇),字尾自動機不會寫?來寫易於理解速度也相當不錯的雜湊吧。

這裡有兩個字串,分別給兩個字串做雜湊,然後二分直接二分答案len,計算兩個字串每個起點開始長度為len的子串的雜湊(o(n)的)。然後給第兩個字串的長度為len的子串的雜湊值排序。列舉第乙個字串的雜湊,在第二個字串的雜湊裡面用lower_bound找(這也是之前給它排序的原因,排好序就可以lower_bound),找到了就說明存在這樣長度的最長公共子串。於是ac**如下(最後總共用時約1800ms,約是字尾自動機的9倍):

#include 

#include

#include

#include

#include

#include

#include

using

namespace

std;

typedef

unsigned

long

long ull;

#define maxn 200003

ull xp[maxn];

ull hasha[maxn];

ull hashb[maxn];

ull ha[maxn];

ull hb[maxn];

char a[maxn], b[maxn];

int x = 233;

int la, lb;

int mlen;

int minlen;

bool check(int len)

return

false;

}int main()

else

r = m-1;

}printf("%d\n", ans);

return

0;}

最長這個條件優先,因此還是二分長度。每次檢查是否存在這樣乙個出現次數超過m次的子串即可。將雜湊值排序可以把雜湊值相同的子串的雜湊值排在一起,這樣之後就能o(n)時間判斷出超過次數是否超過m次。**

/*

submition url:

*/#include

#include

#include

#include

#include

#include

#include

#include

#include

using

namespace

std;

int m;

char str[40002];

typedef

unsigned

long

long ull;

ull h[40002];

ull hhash[40002];

ull xp[40002];

int rrank[40002];

int x = 123;

int slen;

int pos;

bool cmp(int a, int b)

void calc()

bool check(int len)

sort(rrank, rrank+slen-len+1, cmp);

int times = 0;

pos = -1;

for(int i = 0; i < slen-len+1; i++)

return pos >= 0;

}void solve()

int l = 0, r = slen;

int ans = 0;

while(l <= r)

else

r = m-1;

}check(ans);

if(ans)

printf("%d %d\n", ans, pos);

else

puts("none");

}int main()

return

0;}

雜湊用途廣泛,是個非常好的東西。

字串雜湊

參照演算法筆記p109,甲級1039 先假設字串均由大寫字母a z構成。在這個基礎上,不妨把a z視為0 25,這樣就把26個大寫字母對應到了26進製中。接著,按照將26進製轉化為10進製的思路,由進製的轉換結論可知,在進製轉換過程中,得到的10進製肯定是唯一的,由此便可實現將字串對映為整數的需求 ...

字串雜湊

昨天做了一道字串雜湊的題,感覺還好理解。今天的題看了 不知道為什麼,搜來搜去發現不知道的東西還很多,網上找到的東西也都是很零散,書上也沒有系統的講解。先自己整理一下這些零散的知識 關於字串涉及到的演算法大概有 hash kmp trie ac自動機等等,現在還都不明白是怎麼回事,這次先研究字串has...

字串雜湊

給定乙個長度為n的字串,再給定m個詢問,每個詢問包含四個整數l1,r1,l2,r2,請你判斷 l1,r1 和 l2,r2 這兩個區間所包含的字串子串是否完全相同。字串中只包含大小寫英文本母和數字。輸入格式 第一行包含整數n和m,表示字串長度和詢問次數。第二行包含乙個長度為n的字串,字串中只包含大小寫...