void build(int o, int L, int R) { int M = L + (R-L) / 2; if(L == R) minv[o] = a[L]; else { build(2*o, L, M); build(2*o+1, M+1, R); minv[o] = min(minv[2*o], minv[2*o+1]); } }
补题:
1. KMP和AC自动机
KMP复杂度为O(n+m),
void getFail(char* P, int* f) { int m = strlen(P); f[0] = 0; f[1] = 0; //递推边界的初值 for (int i = 1; i < m; i++) { int j = f[i]; while (j && P[i] != P[j]) j = f[j]; //往回走 f[i + 1] = (P[i] == P[j] ? j + 1 : 0); } } void find(char* T, char* P, int * f) { int n = strlen(T), m = strlen(P); getFail(P, f); int j = 0; //当前结点编号 for (int i = 0; i < n; i++) { while (j && P[j] != T[i]) j = f[j]; //顺着失配边走,知道可以匹配 if (P[j] == T[i]) j++; if (j == m) { printf("%d\n", i - m + 1); //找到了一个 j = f[j]; } } }
2. 多个模式串匹配使用AC自动机,组成一个大的状态转移图,而不是每个模式串构造一个转移图。
AC自动机是在Trie树的每个节点加一条fail边,指向当前位置匹配失败时需要跳转到的位置
- Trie的插入、删除复杂度都是O(字符串的长度),因此构建状态转移图是O(模式串长度之和)
- AC自动机在查找所有匹配的位置时,时间复杂度为 O(|S| + m), |S| 是文本串的长度,m是模板串总的匹配数目
3.
- Dijkstra不能用于负权图,S集合和T集合,T集合dis[v]最小的就是点v最终的最短距离,如果存在负边就不一定,所以Dijkstra不能用于负权图,复杂度O(vlogv)
- Bellman-Ford可以处理负权图,当n-1次之后还能进行松弛操作,说明存在负权,复杂度O(VE)
- SPFA只将发生松弛操作的节点入队,因为松弛操作必定发生在前导节点成功松弛的节点上。SPFA在随机的稀疏图上表现出色,并且极其适合带有负边权的图。然而SPFA在最坏情况的时间复杂度与Bellman-Ford算法相同
- Disjkstra适合稠密图
4. 协程
5. 数据库. 这个大坑慢慢补