2019/4/9 奇奇怪怪的笔记

关于代码,基本上是现写的,可能连编译都过不了

因为是简单算法场,所以就很不走心了昂,/小纠结

图论相关 

最小生成树

  • prim,kruskal
  • 最小生成树的切割性质
  • 求次小生成树,动态mst
  • 根据Kruskal的贪心性质,任意两个联通块之间的最小边一定在mst中
  • 非mst一定可以通过一次换边得到权值更小的生成树。

最短路

dijkstra​

priority_queue是什么,我不知道

class dijkstra
{
const ll MN=262144,inf=0x3f3f3f3f
ll d[N];
struct node{ll x;int id;}t[MN<<1];
inline node Min(const node&x,const node&y){return x.x<y.x?x:y;}
inline void rw(int k,ll x){for(t[k+=MN].x=x;k>>=1;)t[k]=Min(t[k<<1],t[k<<1|1]);}\
inline void dij()
{
register int i,x;
for(i=1;i<MN<<1;++i) t[i].x=inf;//init
for(i=1;i<=n;++i) d[t[i+MN].id=i]=inf;//init
for(rw(S,d[S]=0);t[1]!=inf;)
{
rw(x=t[1].id,inf);
for(i=hr[x];i;i=e[i].nex)
if(d[e[i].to]>d[x]+e[i].w) rw(e[i].to,d[e[i].to]=d[x]+e[i].w);
}
}
}

spfa

SLF优化是什么,我不知道

int dis[MN];
bool in[MN];
std::queue<int> q;
bool spfa()
{
memset(dis,0x3f,sizeof dis);
memset(in,0,sizeof in);
reg int i,j;
in[T]=true;q.push(T);dis[T]=0;
while(!q.empty())
{
reg int u=q.front();q.pop();in[u]=false;
for(i=hr[u];i;i=e[i].nex)
if(dis[e[i].to]>dis[u]-e[i].c&&e[i^1].w)
{
dis[e[i].to]=dis[u]-e[i].c;
if(!in[e[i].to]) in[e[i].to]=true,q.push(e[i].to);
}
}
return dis[S]!=inf;
}

floyd

复杂度\(O(n^3)\),倍增floyd

图的联通

强联通分量

边/点双联通分量

割点、割边

圆方树

#define son e[i].to
int dfn[MN],low[MN],ind,st[MN],tp;
void tarjan(int x,int F=0)
{
dfn[x]=low[x]=++ind;st[tp++]=x;
reg int i;
for(i=hr[x];i;i=e[i].nex)if(i^F^1)//防止重边的影响
if(!dfn[son])
{
//如果两个点也算双联通分量的话,直接写(low[son]>=dfn[x])
tj(son,i);low[x]=min(low[x],low[son]);
if(dfn[x]==low[son])
{
++num;ins(x,num,Hr);
for(;st[tp]!=son;--tp) ins(num,st[tp-1],Hr);
}
else if(low[son]>dfn[x]) --tp,ins(x,son,Hr);
}
else low[x]=min(low[x],dfn[son]);
}
  • 两个圆点在圆方树上的路径,与路径上经过的方点相邻的圆点的集合,就等于原图中两点简单路径上的点集
  • 仙人掌上的最短路,圆方树上两个圆点之间权值不变,方点到子节点的边权等于父亲到它的最短路,求距离时,如果\(lca\)时方点,需要暴力转弯

网络流

dinic

\(O(EV^2)\),显然跑不满,对于二分图求匹配这样的特殊情况,复杂度是\(O(E\sqrt V)\)

//懒得写了,反正很熟练了哇
int d[MN],q[MN],top;
bool bfs()
{
memset(d,0,sizeof d);
reg int i,j;
for(d[q[i=top=1]=S]=1;i<=top;++i)
for(j=hr[q[i]];i;i=e[i].nex)
if(e[i].w&&!d[e[i].to])
d[q[++top]=e[i].to]=d[q[i]]+1;
}
int dfs(int x,int f)
{
if(x==T) return f;
int used=0;
for(int &i=cur[x];i;i=e[i].nex)
if(d[e[i].to]==d[x]+1&&e[i].w)
{
int tmp=dfs(e[i].to,min(f-used,e[i].w));
e[i].w-=tmp;e[i^1].w+=tmp;used+=tmp;
if(used==f) return used;
}
return d[x]=-1,used;
}
int dinic()
{
reg int maxflow=0;
while(bfs())
{
memcpy(cur,hr,sizeof cur);
maxflow+=dfs(S,inf);
}
return maxflow;
}

费用流spfa

\(O(\alpha VE)\),据说\(\alpha\)平均不超过\(2\)?

//假设每条边的费用是时间,那么每次增广相当于增大走路的时间
class Flow
{
bool vis[N],inq[N];ll dis[N];queue<int>q;
struct edge{int to,w,c,nex;}e[N*10];int cur[N],hr[N],en;
bool spfa()
{
for(int i=S;i<=T;++i) cur[i]=hr[i],inq[i]=0,dis[i]=1e18;
for(dis[S]=0,inq[S]=1,q.push(S);!q.empty();)
{
int u=q.front();q.pop(),inq[u]=0;
for(int i=hr[u];i;i=e[i].nex)
if(dis[e[i].to]>dis[u]+e[i].c&&e[i].w)
{
dis[e[i].to]=dis[u]+e[i].c;
if(!inq[e[i].to]) inq[e[i].to]=1,q.push(e[i].to);
}
}
return dis[T]<inf;
}
int dfs(int x,int f)
{
if(x==T||!f) return f;vis[x]=1;
int w,used=0;
for(int &i=cur[x];i;i=e[i].nex)
if(dis[e[i].to]==dis[x]+e[i].c&&e[i].w&&!vis[e[i].to])
{
w=dfs(e[i].to,min(f-used,e[i].w));
e[i].w-=w;e[i^1].w+=w;used+=w;
if(used==f) break;
}
vis[x]=0;return used;
}
public:
int S,T;
Flow(){S=0;en=1;}
void ins(int x,int y,int w,int c)
{ dbg1(x);dbg2(y);
e[++en]=(edge){y,w,c,hr[x]},hr[x]=en;
e[++en]=(edge){x,0,-c,hr[y]},hr[y]=en;
}
ll Ans(){ll r=0;while(spfa())r+=dfs(S,inf)*dis[T];return r;}
};

最小割树

//省去dinic部分
void clear(){for(reg int i=2;i<en;i+=2)e[i].w=e[i^1].w=(e[i].w+e[i^1].w)>>1;}
//因为是无向的图所有一开始正向反向边都有容量
void Build(int *id, int n)
{
if(n==1) return;
static int s[MN],t[MN];int cnts=0,cntt=0;
int cut=dinic(id[0],id[1]);
ins(id[0],id[1],cut,Hr,E,En);
for(reg int i=0;i<n;++i)
if(d[id[i]]) s[cnts++]=id[i];
else t[cntt++]=id[i];
memcpy(id,s,cnts<<2);
memcpy(id+cnts,t,cntt<<2);
if(cnts) Build(id,cnts);
if(cntt) Build(id+cnts,cntt);
}

带上下界的网络流?

blog~

树相关

树分治?

不会边分治的蒟蒻。。。

随便放几道题算了:1. 长链剖分 2. 点分治 3. 点分树

LCA?

树剖,倍增

RMQ

int pos[MN],fpos[MN<<2],st[MN<<2][20];//欧拉序,反欧拉序,st表
int dis(int x,int y)
{
if(pos[x]>pos[y]) std::swap(x,y);
reg int k=lg[pos[y]-pos[x]+1];
return fpos[min(st[pos[x]][k],st[pos[y]-(1<<k)+1][k])];
}
void dfs(int x,int fa=0)
{
pos[x]=++ind;fpos[ind]=x;st[ind][0]=ind;reg int i;
for(i=hr[x];i;i=e[i].nex)if(e[i].to^fa)
dfs(e[i].to,x),st[++ind][0]=pos[x];
}
inline void pre_work()
{
reg int i,j;dfs(1);
for(lg[0]=-1,i=1;i<(MN<<2);++i)lg[i]=lg[i>>1]+1;//注意是MN<<2
for(j=1;j<20;++j)for(i-1;i+(1<<j)-1<=ind&&i<=ind;++i)
st[i][j]=min(st[i][j-1],st[i+(1<<(j-1))][j-1]);
}

动态树?prufer编码?, 跳转到前天的笔记

欧拉回路

(偷偷把原来写的东西搬上来。。。)

  1. 判定

    有向图:所有点连通,且入度都等于出度

    无向图:所有点连通,且度数为偶数

    欧拉回路删掉一条边就是欧拉路径

    欧拉路径:有且只有两个不符合欧拉回路要求的点,并且相连后就满足了

  2. 算法

    求欧拉路径就把不满足的点连起来,求欧拉回路后删掉这条边就好了

    无向图

    dfs,标记走过的边以及反边,走过就不走

    每次回溯时记录边,这些边依次构成欧拉回路

    有向图

    边反向

    和无向图差不多

    然后可以当前弧优化

  3. 正确性

    除了第一个点外,其它的点dfs是一定是入边出边成对出现

    所以第一次加入答案的边一定是第一个点的入边

    回溯时这个点又会多走一条出边,那么下次加入的一定是又是这个点的入边

    归纳下去,一定会形成一条回路

namespace undir
{
inline void ins(int u,int v);//略略略
int de[MN],st[MN],top,mark[MN<<1];
void dfs(int u)
{
for(int &i=hr[u];i;i=e[i].nex)if(!mark[i])
{
mark[i]=mark[i^1]=1;int j=i;dfs(e[i].to);//反边反边!
st[++top]=j&1?((j-1)>>1):j>>1;
}
}
void solve();//包括读入,判定,略略略
}
namespace dir
{
inline void ins(int u,int v);//略略略
int ind[MN],outd[MN],st[MN],top,mark[MN];
void dfs(int u)
{
for(int &i=hr[u];i;i=e[i].nex)if(!mark[i])
{
mark[i]=1;int j=i;
dfs(e[i].to);st[++top]=j-1;
}
}
void solve();
}

匈牙利算法

KM算法是什么,我不知道

核心是找到一个起点和终点都在同一个集合的增广路径,路径上相邻的两条边中恰有一个在匹配中

int ans,bel[MN];
bool vis[MN];
bool find(int x)
{
for(int i=hr[x];i;i=e[i].nex)
if(!vis[e[i].to])
{
vis[e[i].to]=true;
if(bel[e[i].to]==-1||find(bel[e[i].to])) return bel[e[i].to]=x,1;
}
return 0;
}
void Main()
{
for(int i=0;i<n;++i)
{
memset(vis,0,sizeof vis);
if(find(i)) ++ans;
}
}

字符串什么的

KMP

找到最大的前缀等于后缀,\(=\)最大的\(border\)

int nex[MN];
void KMP(char *s,int len)
{
int i,k=0;
for(nex[1]=0,i=2;i<=len;++i)
{
while(k&&s[k+1]!=s[i])k=nex[k];
if(s[k+1]==s[i]) nex[i]=++k;
else nex[i]=0;
}
}
int March(char *s,int lens,char *t,int lent)
{
int i,k=0,tot;
for(i=1;i<=lent;++i)
{
while(k&&s[k+1]!=t[i]) k=nex[k];
if(s[k+1]==t[i]) ++k;
if(k==lens) ++tot,k=nex[k];//match!
}
return tot;
}

Z算法

和manacher类似的算法

\(z[i]\)表示\(s[i...]\)和原串的LCP

已知\(z[1...i-1]\),求\(z[i]\)

定义\(r[i]=i+z[i]\),即 \(i\) 后缀和原串的 LCP 在 \(i\) 后缀中的结束位置加\(1\)。

  • 考虑 \(1\) 到 \(i-1\) 中 \(r[k]\) 最大的 \(k\),分成三种情况:
  1. \(i ≥ r[k]\):令 \(z[i] = 0\),往后暴力匹配,更新 \(k\) 为 \(i\)。
  2. \(i < r[k]\) 且 \(r[i-k+1] < z[k]\):\(z[i] = z[i-k+1]\)。
  3. \(i < r[k]\) 且 \(r[i-k+1] ≥ z[k]\):令 \(z[i] = r[k] - i\),往后暴力匹配,更新 \(k\) 为 \(i\)。

均摊 \(O(n)\)。

考虑做字符串匹配,令\(C=B+\)'#'\(+A\),求\(z\)数组,看哪些后缀的\(z\)值等于\(len_B\)

void Z()
{
z[1]=0;r[1]=1;
int i,k=1;
for(i=2;i<=N;++i)
{
if(r[k]<=i) z[i]=1;
else z[i]=min(r[k]-i,z[i-z[k]+1]);
while(i+z[i]<=N&&s[1+z[i]]==s[i+z[i]]) ++z[i];
r[i]=i+z[i];
if(r[i]>=r[k]) k=i;
}
}

AC自动机

class AC_automaton{
private:
int tr[N][26],cnt,e[N],fail[N];
public:
void insert(char *s)
{
int p=0;
for(int i=0;s[i];i++)
{
int k=s[i]-'a';
if(!tr[p][k])tr[p][k]=++cnt;
p=tr[p][k];
}
e[p]++;
}
void build()
{
queue<int>q;
memset(fail,0,sizeof(fail));
for(int i=0;i<26;i++)if(tr[0][i])q.push(tr[0][i]);
while(!q.empty())
{
int k=q.front();q.pop();
for(int i=0;i<26;i++)
if(tr[k][i])
fail[tr[k][i]]=tr[fail[k]][i],q.push(tr[k][i]);
else tr[k][i]=tr[fail[k]][i];
}
}
int query(char *t)
{
int p=0,res=0;
for(int i=0;t[i];i++)
{
p=tr[p][t[i]-'a'];
for(int j=p;j&&~e[j];j=fail[j])res+=e[j],e[j]=-1;
}
return res;
}
}ac;

SA

为什么我的\(SA\)这么长啊啊啊

大佬的博客,供哪天突然不会的我学习

求\(sa\),基数排序

\(height[i]=LCP(sa[i],sa[i-1])\)

\(h[i]=height[rk[i]]\)

\(h[i]\ge h[i-1]-1\)

class SA
{
private:
int height[MN][19],p,q,sa[2][MN],rk[2][MN],num[MN];
public:
SA(){M(height);M(sa);M(rk);M(num);}
inline void init(){M(height);M(sa);M(rk);M(num);}
inline void build_sa()
{
register int i,j,k,mx;
for(i=1;i<=n;++i) num[s[i]-'a'+1]++;
for(i=1;i<=26;++i) num[i]+=num[i-1];
for(i=1;i<=n;++i) sa[1][num[s[i]-'a'+1]--]=i;
for(i=1;i<=n;++i) rk[1][sa[1][i]]=rk[1][sa[1][i-1]]+(s[sa[1][i-1]]!=s[sa[1][i]]);
mx=rk[1][sa[1][n]];
for(p=1,q=0,k=1;k<=n;k<<=1,p^=1,q^=1)
{
if(mx==n) break;
for(i=1;i<=n;++i) num[rk[p][sa[p][i]]]=i;
for(i=n;i;--i) if(sa[p][i]>k) sa[q][num[rk[p][sa[p][i]-k]]--]=sa[p][i]-k;
for(i=n-k+1;i<=n;++i) sa[q][num[rk[p][i]]--]=i;
for(i=1;i<=n;++i)
rk[q][sa[q][i]]=rk[q][sa[q][i-1]]+(rk[p][sa[q][i]]!=rk[p][sa[q][i-1]]||rk[p][sa[q][i]+k]!=rk[p][sa[q][i-1]+k]);
mx=rk[q][sa[q][n]];
}
for(i=k=1;i<=n;++i)
{
if(rk[p][i]==1) continue;if(k) k--;
for(j=sa[p][rk[p][i]-1];j+k<=n&&i+k<=n&&s[i+k]==s[j+k];++k);
height[rk[p][i]][0]=k;
}
for(i=1;i<=18;++i)for(j=n;j>=1&&j>(1<<i);--j)
height[j][i]=min(height[j][i-1],height[j-(1<<i-1)][i-1]);
}
inline int LCP(int x,int y)
{
x=rk[p][x];y=rk[p][y];
if(x>y) std::swap(x,y);
return min(height[y][lg[y-x]],height[x+(1<<lg[y-x])][lg[y-x]]);
}
}

SAM

核心?

  • 作为一种可以表示所有后缀的状态的自动机,它得满足状态数尽可能的小
  • SAM的做法:
    1. 每个状态表示所有\(Right\)集合相同的子串,这里\(Right\)集合的定义可是一个子串在原串中所有出现位置的右端点的集合。
    2. 对于每个状态,我们定义一个\(step\),表示该状态所能表示的所有子串中长度最大值
    3. \(fa\)指针,满足当前串的\(Right\)集合是\(fa\)指向的状态的真子集,且是最大的那一个,可以发现,\(fa\)指针所指向的状态一定是当前状态子串的一个后缀。
    4. 在线加点,每次加点后最多只会增加两个新的状态
class Suf_Automation
{
#define MX 2000005
private:
int c[MX][26],fa[MX],step[MX],v[MX],rk[MX],val[MX];
int last,cnt,n;
ll ans=0;
public:
inline void init(int len)
{
cnt=last=1;n=len;
for(int i=1;i<=n<<1;++i)
memset(c[i],0,sizeof c[i]),step[i]=fa[i]=v[i]=val[i]=0;
}
void Insert(int x)
{
int p=last,np=++cnt;step[np]=step[p]+1;val[np]=1;
for(;p&&!c[p][x];p=fa[p]) c[p][x]=np;
if(!p) fa[np]=1;
else
{
int q=c[p][x];
if(step[q]==step[p]+1) fa[np]=q;
else
{
int nq=++cnt;step[nq]=step[p]+1;
memcpy(c[nq],c[q],sizeof c[q]);
fa[nq]=fa[q];fa[np]=fa[q]=nq;
for(;c[p][x]==q;p=fa[p]) c[p][x]=nq;
}
}
last=np;
}
inline void Query()
{
register int i;
for(i=1;i<=cnt;++i) ++v[step[i]];
for(i=1;i<=n;++i) v[i]+=v[i-1];
for(i=1;i<=cnt;++i) rk[v[step[i]]--]=i;
for(i=cnt;i;--i)
{
val[fa[rk[i]]]+=val[rk[i]];
if(val[rk[i]]>1) ans=max(ans,1ll*val[rk[i]]*step[rk[i]]);
}
val[1]=0;
printf("%lld\n",ans);
}
#undef MX
}pac;

后缀树

咕咕咕

回文树

又称作“回文自动机”

每个节点都是一个回文串,然后\(fail\)指针维护的是它的最大的后缀回文串(同时也是前缀的)。

回文树的用处?

——by \(PinkRabbit\)

  • 统计每个本质不同回文串出现次数的。这个 Manacher 很难做到(需要配合后缀自动机),但是回文自动机可以解决。
  • 有趣的是,回文自动机可以支持前端插入呢,只需要再维护一个指向最长回文前缀的指针 \(head\)就好啦。因为回文是两边对称的呢,所以前端插入也没关系的。注意两个指针要同时更新哦。就是当前字符插完后,整个串形成回文串,那么就要更新\(head\)为当前这一端的\(fail\)

例题:APIO2014 回文串

//APIO 2014 回文串
#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
}
#define MN 300005
int fail[MN],len[MN],cnt[MN];
int c[MN][26],en;ll ans;
char s[MN];
int main()
{
scanf("%s",s+1);
fail[0]=1;len[++en]=-1;
for(int i=1,j=1;s[i];++i)
{
while(s[i]!=s[i-len[j]-1]) j=fail[j];
if(!c[j][s[i]-'a'])
{
len[++en]=len[j]+2;
int k=fail[j];
while(s[i]!=s[i-len[k]-1])
k=fail[k];
fail[en]=c[k][s[i]-'a'];
c[j][s[i]-'a']=en;
}
j=c[j][s[i]-'a'];
++cnt[j];
}
for(int i=en;i>1;i--)
{
ans=max(ans,1ll*cnt[i]*len[i]);
cnt[fail[i]]+=cnt[i];
}
printf("%lld\n",ans);
return 0;
}

manacher

\(abcba\rightarrow a!b!c!b!a\)

记\(p[i]\)表示以\(i\)为回文中心的左右能延伸的最长长度\(+1\)

\(p[1]=1\)

\(r[i]=i+p[i]\)

考虑 \(1\) 到 \(i-1\) 中 \(r[k]\) 最大的 \(k\),分成三种情况:

  1. \(i \geq r[k]\),令\(p[i]=1\),然后暴力更新,更新 \(k\) 为 \(i\)。
  2. \(i < r[k]\)&&\(p[2*k-i]<r[k]-i\),\(p[i]=p[2*k-i]\)
  3. \(i<r[k]\)&&\(p[2*k-i]\geq r[k]-i\),令\(p[i]=r[k]-i\),然后暴力更新,更新 \(k\) 为 \(i\)。
 for(k=p[1]=1,i=r[1]=2;i<=m;++i)
{
if(r[k]<=i) p[i]=1;
else p[i]=min(p[k*2-i],r[k]-i);
for(;s[i+p[i]]==s[i-p[i]];++p[i]);
r[i]=p[i]+i;r[i]>r[k]?k=i:0;p[i]-1>ans?ans=p[i]-1:0;
}

后缀平衡树?咕咕咕


Blog来自PaperCloud,未经允许,请勿转载,TKS!

Note_4.9的更多相关文章

  1. note_4.10

    单位根反演 \[ \frac{1}{k}\sum_{i=0}^{k-1}\omega_k^{in}=[k|n] \] 所以 \[ \begin{equation} \begin{split} \sum ...

  2. Note_4.7

    2019/4/7 奇奇怪怪的笔记 狄利克雷卷积  \(μ∗1=ϵ\),莫比乌斯反演 \(Id=φ∗1⇒φ=μ∗Id\) \(d=1∗1⇒1=μ∗d\) \(σ=Id∗1⇒Id=μ∗σ\) \(σ=φ∗ ...

  3. Note_4.1

    2019/4/1 奇奇怪怪的笔记 多项式除法 问题描述 给定\(n\)次多项式\(A(x)\)和\(m\)次多项式\(B(x)\) 求: \[ A(x)=B(x)*C(x)+R(x) \] 我们要求\ ...

  4. boost::xml——基本操作以及中文乱码解决方案

    下面是本人使用boost库的xml部分的基础操作,并且解决对于大家使用boost库读写中文xml内容出现的乱码问题. 1.实现boost库xml基本操作2.解决boost对xml中中文乱码问题3.实现 ...

  5. Spring MVC(3)Spring MVC 高级应用

    一.Spring MVC 的数据转换和格式化 前面的应用,都只是用HandlerAdapter去执行处理器. 处理器和控制器不是一个概念,处理器是在控制器功能的基础上加上了一层包装,有了这层包装,在H ...

  6. Spring MVC(2)Spring MVC 组件开发

    一.控制器接收各类请求参数 代码测试环境: 接收各类参数的控制器--ParamsController package com.ssm.chapter15.controller; @Controller ...

随机推荐

  1. NEST explain

    Elasticsearch 的相似度算法 被定义为检索词频率/反向文档频率, TF/IDF ,包括以下内容: 检索词频率 检索词在该字段出现的频率?出现频率越高,相关性也越高. 字段中出现过 5 次要 ...

  2. NEST 字符串sort

    text字符串sort会先分词.可先建立filed字段.并设置为keyword mapping public void Mapping() { var response = client.IndexE ...

  3. JAVA日期格式化yyyyMMddHHmmssSSS

    String nowtime = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date());

  4. vue应用难点总结

    一.父子组件生命周期 父组件create->子组件create->子组件mounted->父组件mounted 当一个钩子函数使用了异步请求时,并不会等该钩子函数中所有异步的回调都执 ...

  5. sql 树形递归查询

    sql 树形递归查询: with ProductClass(ClassId,ClassName) as ( union all select c.ClassId,c.ClassName from Cl ...

  6. SQL SERVER-CROSS APPLY

    CROSS APPLY和 OUTER APPLY 区别详解 SQL Server 2005 新增 cross apply 和 outer apply 联接语句,增加这两个东东有啥作用呢? 我们知道有个 ...

  7. Django异常 - ImportError: No module named django.core.management

    Django错误 - ImportError: No module named django.core.management问题描述:在命令行输入 manage.py runserver,提示找不到d ...

  8. 绘图 Matplotlib Numpy Pandas

    丈夫气力全,一个拟当千.猛气冲心出,视死亦如眠. 绘图 Matplotlib可视化是在整个数据挖掘的关键辅助工具,可以清晰的理解数据,从而调整我们的分析方法. 能将数据进行可视化,更直观的呈现使数据更 ...

  9. swagger是什么OpenAPI是什么

    wiki: https://en.wikipedia.org/wiki/OpenAPI_Specification 官网: https://swagger.io/specification/

  10. Linux命令——df

    参考:12 Useful “df” Commands to Check Disk Space in Linux 简介 df用于查看文件系统磁盘空间使用情况. df 读取的数据几乎都是针对一整个文件系统 ...