核心思想:將字串看成p進製數,p的經驗值是131或13331,取這兩個值的衝突概率低
小技巧:取模的數用2
^64,這樣直接用unsigned
long
long儲存,溢位的結果就是取模的結果
typedef
unsigned
long
long ull;
ull h[n]
, p[n]
;// h[k]儲存字串前k個字母的雜湊值, p[k]儲存 p^k mod 2^64
// 初始化p[0
]=1;
for(
int i =
1; i <= n; i ++
)// 計算子串 str[l ~ r] 的雜湊值
ull get
(int l,
int r)
很久很久以前,森林裡住著一群兔子。有一天,兔子們想要研究自己的 dna 序列。
我們首先選取乙個好長好長的 dna 序列(小兔子是外星生物,dna 序列可能包含 26 個小寫英文本母)。
然後我們每次選擇兩個區間,詢問如果用兩個區間裡的 dna 序列分別生產出來兩隻兔子,這兩個兔子是否一模一樣。
注意兩個兔子一模一樣只可能是他們的 dna 序列一模一樣。
輸入格式
第一行輸入乙個 dna 字串 s。
第二行乙個數字 m,表示 m 次詢問。
接下來 m 行,每行四個數字 l1,r1,l2,r2,分別表示此次詢問的兩個區間,注意字串的位置從1開始編號。
輸出格式
對於每次詢問,輸出一行表示結果。
如果兩隻兔子完全相同輸出 yes,否則輸出 no(注意大小寫)。
資料範圍
1≤length(s),m≤1000000
輸入樣例:
aabbaabb
31 3 5 7
1 3 6 8
1 2 1 2
輸出樣例:
yesno
yes
模板題,套用上面的模板即可
#include
#include
using
namespace std;
typedef
unsigned
long
long ull;
const
int n =
1000010
, base =
131;
int h[n]
, p[n]
;char str[n]
;int
get(
int l,
int r)
intmain()
int m;
scanf
("%d"
,&m)
;while
(m--
)return0;
}
如果乙個字串正著讀和倒著讀是一樣的,則稱它是回文的。給定乙個長度為n的字串s,求他的最長回文子串的長度是多少。
輸入格式
輸入將包含最多30個測試用例,每個測試用例佔一行,以最多1000000個小寫字元的形式給出。
輸入以乙個以字串「end」(不包括引號)開頭的行表示輸入終止。
輸出格式
對於輸入中的每個測試用例,輸出測試用例編號和最大回文子串的長度(參考樣例格式)。
每個輸出佔一行。
輸入樣例:
abcbabcbabcba
abacacbaaaab
end輸出樣例:
case 1: 13
case 2: 6
套用字串雜湊演算法。算出正序,逆序雜湊。列舉中點,然後二分半徑。
技巧:在字元之間插入乙個#,這樣字串長度就變成了偶數,但要注意的是:算原來字元長度的時候
要判斷第乙個字元是什麼,如果不是#,這樣字元長度就是半徑+1,否則就是半徑。
#include
#include
#include
using
namespace std;
typedef
unsigned
long
long ull;
const
int n =
2000010
, base =
131;
char str[n]
;ull hl[n]
, hr[n]
, p[n]
;ull get
(ull h,
int l,
int r)
intmain()
n = n *2;
//注意要更新n
p[0]
=1;for
(int i =
1, j = n; i <= n; i++
, j--
)int res =0;
for(
int i =
1; i <= n; i++
)//列舉中點
if(str[i - l]
<=
'z') res =
max(res, l +1)
;else res =
max(res, l);}
printf
("case %d: %d\n"
, t++
, res);}
return0;
}
字尾陣列 (sa) 是一種重要的資料結構,通常使用倍增或者dc3演算法實現,這超出了我們的討論範圍。在本題中,我們希望使用快排、hash與二分實現乙個簡單的o(nlog2n)的字尾陣列求法。
詳細地說,給定乙個長度為 n 的字串s(下標 0~n-1),我們可以用整數 k(0≤k先想出樸素做法:用乙個下標表示字串字尾的開頭。然後使用快排對這些字尾排序。
比較函式:挨個字元比較。
求兩個字串的最長公共字首長度,可以用字串雜湊的做法。即二分列舉最大長度,如何判斷
這兩個字串是相同的呢?可以求出在這個長度下的字串雜湊值,通過比較雜湊值,判斷在這兩個字串是不是相同的字串。
優化比較函式:可以先求出兩個字尾的最大公共長度,然後比較最大公共長度後乙個字元的大小即可。
#include
#include
#include
#include
using
namespace std;
typedef
unsigned
long
long ull;
const
int n =
300010
, base =
131;
char str[n]
;int sa[n]
;ull h[n]
, p[n]
;int n;
ull get
(int l,
int r)
//二分獲取最大公共長度
intget_max_common_prefix
(int a,
int b)
return l;
}//比較函式
bool
cmp(
int a,
int b)
intmain()
sort
(sa +
1, sa + n +
1, cmp)
;//排索引
for(
int i =
1; i <= n; i++
)printf
("%d "
, sa[i]-1
);puts(""
);for(
int i =
1; i <= n; i++
)puts
(" ");
return0;
}
字串雜湊 模板
以下文字 據我的理解,hash就是乙個像函式一樣的東西,你放進去乙個值,它給你輸出來乙個值。輸出的值就是hash值。一般hash值會比原來的值更好儲存 更小 或比較。那字串hash就非常好理解了。就是把字串轉換成乙個整數的函式。而且要盡量做到使字串對應唯一的hash值。字串hash的種類還是有很多種...
模板 字串雜湊
如題,給定n個字串 第i個字串長度為mi,字串內包含數字 大小寫字母,大小寫敏感 請求出n個字串中共有多少個不同的字串。第一行包含乙個整數n,為字串的個數。接下來n行每行包含乙個字串,為所提供的字串。輸出包含一行,包含乙個整數,為不同的字串個數。s am plei nput sample input...
字串雜湊(模板)
尋找長度為n的主串s中的匹配串t 長度為m 出現的位置或次數屬於字串匹配問題。字串雜湊就是將每個字串轉化為乙個數值,然後遍歷主串,判斷在主串起始位置為i長度為m的字串的雜湊值與匹配串的雜湊值是否相等即可,每次判斷為o 1 的時間。這樣就可以轉化為o n 的時間完成判斷。若求字串中第i位到第j位的雜湊...