常用算法模板——数据结构
单链表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 int head, e[N], ne[N], idx;void init () { head = -1 ; idx = 0 ; } void insert (int a) { e[idx] = a, ne[idx] = head, head = idx++; } void remove () { head = ne[head]; }
双链表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 int e[N], l[N], r[N], idx;void init () { r[0 ] = 1 , l[1 ] = 0 ; idx = 2 ; } void insert (int a, int x) { e[idx] = x; l[idx] = a, r[idx] = r[a]; l[r[a]] = idx, r[a] = idx++; } void remove (int a) { l[r[a]] = l[a]; r[l[a]] = r[a]; }
栈
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 int stk[N], tt = 0 ;stk[++tt] = x; tt--; stk[tt]; if (tt > 0 ) {}
队列
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 int q[N], hh = 0 , tt = -1 ;q[++tt] = x; hh++; q[hh]; if (hh <= tt) {}
循环队列
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 int q[N], hh = 0 , tt = 0 ;q[tt++] = x; if (tt == N) tt = 0 ;hh++; if (hh == N) hh = 0 ;q[hh]; if (hh != tt) {}
单调栈
1 2 3 4 5 6 int tt = 0 ;for (int i = 1 ; i <= n; i++) { while (tt && check (stk[tt], i)) tt--; stk[++tt] = i; }
单调队列
1 2 3 4 5 6 7 int hh = 0 , tt = -1 ;for (int i = 0 ; i < n; i++) { while (hh <= tt && check_out (q[hh])) hh++; while (hh <= tt && check (q[tt], i)) tt--; q[++tt] = i; }
KMP
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 for (int i = 2 , j = 0 ; i <= m; i++) { while (j && p[i] != p[j + 1 ]) j = ne[j]; if (p[i] == p[j + 1 ]) j++; ne[i] = j; } for (int i = 1 , j = 0 ; i <= n; i++) { while (j && s[i] != p[j + 1 ]) j = ne[j]; if (s[i] == p[j + 1 ]) j++; if (j == m) { j = ne[j]; } }
Trie 树
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 int son[N][26 ], cnt[N], idx;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]; }
并查集
朴素并查集
1 2 3 4 5 6 7 8 9 10 11 12 13 int p[N]; int find (int x) { if (p[x] != x) p[x] = find (p[x]); return p[x]; } for (int i = 1 ; i <= n; i++) p[i] = i;p[find (a)] = find (b);
维护 size 的并查集
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 int p[N], size[N];int find (int x) { if (p[x] != x) p[x] = find (p[x]); return p[x]; } for (int i = 1 ; i <= n; i++) { p[i] = i; size[i] = 1 ; } size[find (b)] += size[find (a)]; p[find (a)] = find (b);
维护到祖宗节点距离的并查集
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 int p[N], d[N];int find (int x) { if (p[x] != x) { int u = find (p[x]); d[x] += d[p[x]]; p[x] = u; } return p[x]; } for (int i = 1 ; i <= n; i++) { p[i] = i; d[i] = 0 ; } p[find (a)] = find (b); d[find (a)] = distance;
堆
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 int h[N], ph[N], hp[N], size;void heap_swap (int a, int b) { swap (ph[hp[a]], ph[hp[b]]); swap (hp[a], hp[b]); swap (h[a], h[b]); } void down (int u) { int t = u; if (u * 2 <= size && h[u * 2 ] < h[t]) t = u * 2 ; if (u * 2 + 1 <= size && h[u * 2 + 1 ] < h[t]) t = u * 2 + 1 ; if (u != t) { heap_swap (u, t); down (t); } } void up (int u) { while (u / 2 && h[u] < h[u / 2 ]) { heap_swap (u, u / 2 ); u >>= 1 ; } } for (int i = n / 2 ; i; i--) down (i);
一般哈希
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 int h[N], e[N], ne[N], idx;void insert (int x) { int k = (x % N + N) % N; e[idx] = x; ne[idx] = h[k]; h[k] = idx++; } bool find (int x) { int k = (x % N + N) % N; for (int i = h[k]; i != -1 ; i = ne[i]) if (e[i] == x) return true ; return false ; } int h[N];int find (int x) { int t = (x % N + N) % N; while (h[t] != null && h[t] != x) { t++; if (t == N) t = 0 ; } return t; }
字符串哈希
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 typedef unsigned long long ULL;ULL h[N], p[N]; p[0 ] = 1 ; for (int i = 1 ; i <= n; i++) { h[i] = h[i - 1 ] * P + str[i]; p[i] = p[i - 1 ] * P; } ULL get (int l, int r) { return h[r] - h[l - 1 ] * p[r - l + 1 ]; }
相关内容