複習(二):KMP、Trie、最大異或對、
————————————————————2020年10月25日(週日)
一、KMP
第四次了,發現還是記不住……因為之前沒好好做筆記……
答案&註釋
#include <iostream>
using namespace std;
const int N = 100010, M = 1000010;
int n, m;
int ne[N];
char s[M], p[N];
int main()
{
cin >> n >> p + 1 >> m >> s + 1;
//首先是處理好ne陣列,作用是當匹配不成功時,嘗試從上一個出現當前字元的地方開始找,不至於從頭再來。
for (int i = 2, j = 0; i <= n; i ++ )
{
//這裡就是一點一點地往回退,從頭開始太傻了。
while (j && p[i] != p[j + 1]) j = ne[j];
//找到可以往後一步的地方就j加1
if (p[i] == p[j + 1]) j ++ ;
//然後將對應i位置的ne設為j
ne[i] = j;
}
//開始尋找,其實兩者程式碼是差不多的,因為找的時候也是一步一步往回退著找的。
for (int i = 1, j = 0; i <= m; i ++ )
{
while (j && s[i] != p[j + 1]) j = ne[j];
if (s[i] == p[j + 1]) j ++ ;
if (j == n)
{
printf("%d ", i - n);
j = ne[j];
}
}
return 0;
}
二、Trie
轉
理解之後覺得挺簡單的,就這樣吧。
連註釋都不注的答案
#include<bits/stdc++.h>
using namespace std;
const int N = 100010;
int son[N][26], cnt[N], idx;
char str[N];
void insert(char *str){
int p = 0;
for(int i = 0; str[i]; i ++){
int u = str[i] - 'a';
if(!son[p][u]) son[p][u] = ++idx;
p = son[p][u];
}
cnt[p] ++;
}
int query(char *str){
int p = 0;
for(int i = 0 ; str[i]; i ++){
int u = str[i] - 'a';
if(!son[p][u]) return 0;
p = son[p][u];
}
return cnt[p];
}
int main(){
int n;
scanf("%d", &n);
while(n --){
char op[2];
scanf("%s%s", op, str);
if(*op == 'I') insert(str);
else printf ("%d\n", query(str));
}
return 0;
}
三、最大異或對
傳送
一週前剛刷完……
(然而過了一週後再看,發現又忘記怎麼做了……我的記憶果然是假的。
不過這次刷完Trie
之後再看,發現其實做法和Trie
真的很像,就是Trie
的一種運用。
(注:-1的二進位制碼全是 1,所以 ~-1 == 0 !
註釋版 & 思路
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010, M = 3000000;
int n;
int a[N], son[M][2], idx;
void insert(int x)
{
int p = 0;
for (int i = 30; i >= 0; i -- )
{
int &s = son[p][x >> i & 1];
if (!s) s = ++ idx;
p = s;
}
}//這個函式就是說,將這個數分解為一個二進位制數,然後按照這個二進位制不斷地往下開闢一條道路
//每到一個新節點就給它取一個新的名字,這樣往下找兒子的時候就不會產生混亂……
int search(int x)
{
int p = 0, res = 0;
for (int i = 30; i >= 0; i -- )
{
int s = x >> i & 1;
if (son[p][!s])
{
res += 1 << i;
p = son[p][!s];
}
else p = son[p][s];
}
return res;
}
int main()
{
scanf("%d", &n);
for (int i = 0; i < n; i ++ )
{
scanf("%d", &a[i]);
insert(a[i]);
}
int res = 0;
for (int i = 0; i < n; i ++ ) res = max(res, search(a[i]));
printf("%d\n", res);
return 0;
}
To be continue……
相關文章
- 最大異或對
- poj 3764 最長異或路徑(二進位制trie樹)
- 異或之Kth[1] (可持久化二進位制trie樹)持久化
- 藍橋複習——KMPKMP
- P4551 最長異或路徑(樹上字首異或01-trie)
- Trie——解決字串搜尋、異或最值問題字串
- 字串演算法--$\mathcal{KMP,Trie}$樹字串演算法KMP
- 雙子串最大異或 題解
- UOJ Round #15 [構造 | 計數 | 異或雜湊 kmp]KMP
- 《演算法筆記一》複雜度、排序、二分、異或演算法筆記複雜度排序
- 子陣列的最大異或和問題陣列
- 演算法之字首樹——最大異或和演算法
- iOS複習(二)iOS
- 異或
- 洛谷題單指南-字串-P4735 最大異或和字串
- canvas複習總結(二)Canvas
- jquery複習總結二jQuery
- 異或門
- 面試複習筆記二(javaweb)面試筆記JavaWeb
- 菜狗的KMP學習KMP
- Trie
- Java中"與"、"或"、"非"、"異或"Java
- java物件導向複習總結(異常)Java物件
- G64【模板】線性基 貪心法 P3812 最大異或和
- 異或雜湊
- JavaScript 複習之各類事件(二)JavaScript事件
- KMP字串匹配學習筆記KMP字串匹配筆記
- 異常執行緒的相關複習(前)執行緒
- 遊戲異或加解密遊戲解密
- 異或線性基
- 位運算-異或(^)
- 413周賽·第四題 - 3277. 查詢子陣列最大異或值陣列
- 對2個hex(16進位制)字串進行異或操作字串
- 計算機二級Java複習1計算機Java
- NoSQL 複習 (二)HBase基本原理SQL
- 第二階段複習——組合
- 字串學習總結(Hash & Manacher & KMP)字串KMP
- 複習java面對物件(方法重寫)Java物件