Random
keaucucal
NAME | keaucucal
BIRTH | 2008
FROM | Taoyuan
CLASS | 106
HATE | IanWen
PHOTO | Not Availible
NOTE: Hello World!
WHOAMI
Random
keaucucal
WHOAMI
NAME | keaucucal
BIRTH | 2008
FROM | Taoyuan
CLASS | 106
HATE | IanWen
PHOTO | Not Availible
NOTE: Hello World!
INDEX
introduction
k-th smallest
hash
1.QuickSort
2.What is random
3.How to random
4.Classification
1.QuickSort
2.QuickSelect
1.Hashing
2.Collision
3.Polynomial
4.Problems
WHOAMI
NAME | keaucucal
BIRTH | 2008
FROM | Taoyuan
CLASS | 106
HATE | IanWen
PHOTO | Not Availible
NOTE: Hello World!
Introduction
QuickSort
void quickSort(int l, int r) {
int pivot = arr[r];
... // 把小於 pivot 的放左邊,大於的放右邊
quickSort(l, pivotIndex - 1);
quickSort(pivotIndex + 1, r);
}
QuickSort
void quickSort(int l, int r) {
int pivot = arr[r];
... // 把小於 pivot 的放左邊,大於的放右邊
quickSort(l, pivotIndex - 1);
quickSort(pivotIndex + 1, r);
}
期望
最壞
(r - l) / 2
(r - l) / 2
1
(r - l) - 1
如何防止惡意測資?
void quickSort(int l, int r) {
int pivotIndex = l + rand() % (r - l + 1);
... // 把小於 pivot 的放左邊,大於的放右邊
quickSort(l, pivotIndex - 1);
quickSort(pivotIndex + 1, r);
}
{1, 2, 3, 4, 5, 6}
Random
What is ? ? ?
Random
A algorithm that use
function.
How to Random?
#include <iostream>
using namespace std;
int main() {
srand(time(NULL)); // 設定亂數種子等於當前時間
int x = rand(); // 0 ~ RAND_MAX
cout << x;
}
Rand()
#include <iostream>
#include <random>
using namespace std;
int main() {
// 使用種子初始化 mt19937
mt19937 gen(807);
// 定義範圍在 1 到 100 之間的均勻分佈
uniform_int_distribution<> dis(1, 100);
cout << dis(gen);
}
mt19937
- 高度的隨機性
- 高效率
- 高均勻分布
How to Random?
Las Vegas
Monte Carlo
- 簡單
優點?
缺點?
- 隨機性差(容易重複)
- 生成範圍限制
- 不同電腦結果不固定
就算種子固定
Rand()
mt19937
Las Vegas
Monte Carlo
有可能給出錯誤答案
一定給出正確答案
但運行速度隨機
隨機的分類
Las Vegas
Monte Carlo
有可能給出錯誤答案
一定給出正確答案
但運行速度隨機
讓錯誤機率變小
別出現Worst Case
隨機的分類
Las Vegas
Monte Carlo
有可能給出錯誤答案
一定給出正確答案
但運行速度隨機
讓錯誤機率變小
別出現Worst Case
隨機的分類
k-th Smallest
int main() {
sort(arr.begin(), arr.end());
cout << arr[k]; // 1-based
}
void quickSort(int l, int r) {
int pivotIndex = l + rand() % (r - l + 1);
... // 把小於 pivot 的放左邊,大於的放右邊
quickSort(l, pivotIndex - 1);
quickSort(pivotIndex + 1, r);
}
Smaller
Pivot
Bigger
QuickSort
QuickSort
void quickSort(int l, int r) {
int pivotIndex = l + rand() % (r - l + 1);
... // 把小於 pivot 的放左邊,大於的放右邊
quickSort(l, pivotIndex - 1);
quickSort(pivotIndex + 1, r);
}
Smaller
Pivot
Bigger
如果 k 在這?
QuickSort
void quickSort(int l, int r) {
int pivotIndex = l + rand() % (r - l + 1);
... // 把小於 pivot 的放左邊,大於的放右邊
quickSort(l, pivotIndex - 1);
quickSort(pivotIndex + 1, r);
}
Smaller
Pivot
Bigger
如果 k 在這?
void quickSort(int l, int r) {
int pivotIndex = l + rand() % (r - l + 1);
... // 把小於 pivot 的放左邊,大於的放右邊
if (k == pivotIndex) {
cout << k;
} else if (k < pivotIndex) {
quickSort(l, pivotIndex - 1); // 只排左邊
} else {
quickSort(pivotIndex + 1, r); // 只排右邊
}
}
Smaller
Pivot
Bigger
QuickSort
QuickSelect
其實這叫做
QuickSelect
其實這叫做
void quickSort(int l, int r) {
int pivotIndex = l + rand() % (r - l + 1);
... // 把小於 pivot 的放左邊,大於的放右邊
if (k == pivotIndex) {
cout << k;
} else if (k < pivotIndex) {
quickSort(l, pivotIndex - 1); // 只排左邊
} else {
quickSort(pivotIndex + 1, r); // 只排右邊
}
}
其實這叫做
#include <bits/stdc++.h>
using namespace std;
vector<int> arr = {10, 4, 5, 8, 6, 11, 26};
int k = 3; // 0-based -> 4th smallest
int quickSelect(int l, int r) {
if (l == r) {
return arr[l];
}
int pivotIndex = l + rand() % (r - l + 1);
swap(arr[pivotIndex], arr[r]); // 換到最後
int pivot = arr[r];
pivotIndex = l;
for (int j = l; j < r; j++) {
if (arr[j] <= pivot) {
swap(arr[pivotIndex], arr[j]);
pivotIndex++;
}
}
swap(arr[pivotIndex], arr[r]);
// 判斷往哪邊搜
if (k == pivotIndex) {
return arr[k];
} else if (k < pivotIndex) {
return quickSelect(l, pivotIndex - 1);
} else {
return quickSelect(pivotIndex + 1, r);
}
}
int main() {
srand(time(NULL));
cout << "The " << k + 1 << "rd smallest element is: "
<< quickSelect(0, arr.size() - 1) << endl;
}
Hash
另外一個Random運用
將輸入轉換成固定格式輸出的過程。
For Example:
讀入一個數字,返回他除以某個數的餘數
- 25 % 10 = 5
- 37 % 10 = 7
- 100 % 10 = 0
807 % 10 = ?
碰撞啦
Hashing
有無限種輸入,但有限種輸出,當輸入不一樣但輸出一樣時,稱為碰撞
假設最後會 % B
場景1:兩個數字比對
場景2:一個數字跟n個數字比對
場景3:n個數字互相比對
B | 場景1 | 場景2 | 場景3 |
---|---|---|---|
1e3 | 0.001000 | 1.000000 | 1.000000 |
1e6 | 0.000001 | 0.632121 | 1.000000 |
1e9 | 0.000000 | 0.001000 | 1.000000 |
1e12 | 0.000000 | 0.000000 | 0.393469 |
1e15 | 0.000000 | 0.000000 | 0.000500 |
1e18 | 0.000000 | 0.000000 | 0.000001 |
碰撞機率
生日悖論
其實只要23個人,某兩人同天生日機率就大於一半了
什麼是碰撞?
string A, B;
cin >> A >> B;
if (A == B) { // O(n)
cout << "YES\n";
} else {
cout << "NO\n";
}
string A, B;
cin >> A >> B;
// precalculate hash value in O(n)
int a = A.getHash(), b = B.getHash();
if (a == b) { // O(1)
cout << "YES\n";
} else {
cout << "NO\n";
}
What for ?
比較兩個東西是否一樣
如果哈希值一樣
-> 可能不一樣
如果哈希值不一樣
-> 一定不一樣
Monte Carlo
What for ?
比較兩個東西是否一樣
string A, B;
cin >> A >> B;
// O(n) get hash value
int a = A.getHash(), b = B.getHash();
if (a == b) { // O(1)
cout << "YES\n";
} else {
cout << "NO\n";
}
多項式 Hashing
A跟B怎麼決定?
A=2593 B=172 ?
然後你就會發現這樣"keaucucal"跟"cjtsai"是同個hash value欸
那所以就
挑個質數
不然就來
RANDOM 囉
就不會被暴力碰撞了
多項式 Hashing
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
struct RandomizedHash {
vector<ll> hash, power; // 哈希值前綴和 / 紀錄Base冪次
ll MOD, BASE; // B / A
RandomizedHash(const string &s) {
mt19937 rng(807); // 設定random number generator的種子為807
uniform_int_distribution<> dist(257, 1e9 + 7); // 設定範圍為 257 ~ 1000000007
MOD = dist(rng); // 隨機設定B
BASE = dist(rng); // 隨機設定A
int n = s.size();
hash.resize(n + 1, 0);
power.resize(n + 1, 1);
for (int i = 0; i < n; i++) {
hash[i + 1] = (hash[i] * BASE + s[i]) % MOD;
power[i + 1] = (power[i] * BASE) % MOD;
}
}
ll getHash(int l, int r) {
// 取得l ~ r 子字串的哈希值
return (hash[r + 1] - hash[l] * power[r - l + 1] % MOD + MOD) % MOD;
}
};
int main() {
string input;
cout << "Enter a string: ";
getline(cin, input);
RandomizedHash hasher(input);
cout << "Hash of the entire string: " << hasher.getHash(0, input.length() - 1) << endl;
}
題目
找出字符串的所有週期長度
可以通過重複那一個前綴來生成整個字串
= 找出有幾個前綴,
給你N個字串
M個詢問
問你第M個字串在N個裡面重複幾個
575919122
沒了 你猜到這是什麼的Hash Value我請你喝飲料
更:答案是807sodian 被猜出來了
Random
By keaucucal
Random
We've added support for incredibly smooth animations between code blocks. See it in action in this deck!
- 338