通过模式串前后缀的自我匹配的长度,计算 next 函数,给 j 指针打一张表,失配时就跳到 next[j] 的位置继续匹配。
next函数
next[i] 表示模式串 P[1..i] 中相等前后缀的最长长度
P a a b a a b a a a a ne[1]=0 a ne[2]=1 a a ne[3]=0 a a b ne[4]=1 a a b a ne[5]=2 a a b a a ne[6]=3 a a b a a b ne[7]=4 a a b a a b a ne[8]=5 a a b a a b a a ne[9]=2 a a b a a b a a a ne[10]=2 a a b a a b a a a a
定义双指针:i 扫描模式串,j 扫描前缀。 初始化,ne[1]=0, i=2, j=0。 每轮 for 循环,i 向右走一步。
#include<bits/stdc++.h> #define int long long usingnamespace std;
int n,m; int dfn[1000010], low[1000010], tot=0;
stack<int>stk; bool instk[1000010];
int num; int scc[1000010], siz[1000010];
structEdge { int from, to, next; }edge[1000010]; int head[1000010], cnt=0; voidadd(int u, int v) { edge[cnt].from=u; edge[cnt].to=v; edge[cnt].next=head[u]; head[u]=cnt++; }
割点判定法则: 如果 x 不是根节点,当搜索树上存在 x 的一个子节点 y,满足 **low[y]≥dfn[x]**,那么 x 就是割点。 如果 x 是根节点,当搜索树上存在至少两个子节点 y1,y2,满足上述条件,那么 x 就是割点。
low[y]≥dfn[x],说明从 y 出发,在不通过 x 点的前提下,不管走哪条边,都无法到达比 x 更早访问的节点。故删除 x 点后,以 y 为根的子树 subtree(y) 也就断开了。即环顶的点割得掉。 反之,若 low[y]<dfn[x],则说明 y 能绕行其他边到达比 x 更早访问的节点,x 就不是割点了。即环内的点割不掉。
int dfn[MAXN], low[MAXN], tot=0; int scc[MAXN], siz[MAXN];
bool cut[MAXN];
structEdge { int from, to, next; }edge[MAXN*2]; int head[MAXN], cnt=0; voidadd(int u, int v) { edge[cnt].from=u; edge[cnt].to=v; edge[cnt].next=head[u]; head[u]=cnt++; }
割边判定法则: 当搜索树上存在 x 的一个子节点 y,满足 **low[y]>dfn[x]**,则 (x,y) 这条边就是割边。
low[y]>dfn[x],说明从 y 出发,在不经过 (x,y) 这条边的前提下,不管走哪条边,都无法到达 x 或 更早访问的节点。故删除 (x,y) 这条边,以 y 为根的子树 subtree(y) 也就断开了。即环外的边割得断。 反之,若 low[y]<=dfn[x],则说明 y 能绕行其他边到达 x 或更早访问的节点,(x,y) 就不是割边了。即环内的边割不断。
int dfn[MAXN], low[MAXN], tot=0; int scc[MAXN], siz[MAXN];
bool cut[MAXN*2];
structEdge { int from, to, next, cut=false; }edge[MAXN*2]; int head[MAXN], cnt=0; voidadd(int u, int v) { edge[cnt].from=u; edge[cnt].to=v; edge[cnt].next=head[u]; head[u]=cnt++; }
structEdge { int from, to, next; }edge[1000010]; int head[1000010], cnt=0; voidadd(int x, int y) { edge[cnt].from=x; edge[cnt].to=y; edge[cnt].next=head[x]; head[x]=cnt++; }
int n,m,s,a,b; // dep存节点深度,fa[u][i]存从u点向上跳2^i次的节点(i从0开始计算) int dep[500010], fa[500010][20];
voiddfs(int u, int father) { dep[u]=dep[father]+1; fa[u][0]=father;
#include<bits/stdc++.h> #define int long long usingnamespace std;
// union-find int ufa[1000010]; intfind(int x) { if(ufa[x]==x) return x; elsereturn ufa[x]=find(ufa[x]); } voidmerge(int a, int b) { ufa[find(a)]=find(b); }
structNode { int from, to, weight; }node[1000010]; boolcmp(Node a, Node b) { return a.weight>b.weight; } bool vis[1000010]; bool dfs_vis[1000010];
structEdge { int to, next, weight; }edge[1000010]; int head[1000010], cnt=0; voidadd(int x, int y, int z) { edge[cnt].to=y; edge[cnt].weight=z; edge[cnt].next=head[x]; head[x]=cnt++; }
// dep存节点深度,fa[u][i]存从u点向上跳2^i次的节点(i从0开始计算) int dep[500010], fa[500010][30]; int minn[500010][30];
voiddfs(int u, int father) { dfs_vis[u]=true; dep[u]=dep[father]+1; fa[u][0]=father;
boolcmp(Edge a, Edge b) { return a.weight<b.weight; }
int fa[maxn]; intfindroot(int x){ return fa[x] == x ? x : fa[x] = findroot(fa[x]); } voidMerge(int x, int y){ x = findroot(x); y = findroot(y); fa[x] = y; }
// Djikstra + Priority_Queue structNode{ int id; int dis; booloperator< (const Node &x)const { return x.dis<dis; } };
int head[100010], cnt; structEdge{ int to, weight, next; }edge[200010]; voidadd(int u, int v, int w) { edge[cnt].to=v; edge[cnt].weight=w; edge[cnt].next=head[u]; head[u]=cnt++; }