2019牛客多校第四场 I题 后缀自动机_后缀数组_求两个串de公共子串的种类数
@
求若干个串的公共子串个数相关变形题
- 牛客这题题意大概是求一个长度为\(2e5\)的字符串有多少个不同子串,若\(s==t\)或\(s==rev(t)\)则认为子串\(s,t\)相同。我们知道回文串肯定和他的反串相同。
- 链接:传送门。
做法1:
- \(yx\)大佬秒出思路%%,对\(s\)串建后缀自动机,可以得到串\(s\)本质不同的子串的个数\(all\),然后只要能减去有多少个串\(x\)的\(rev(x)\)同时也出现了即可。
- 考虑先求出\(s\)和\(rev(s)\)的本质不同的公共子串的数量\(res\),串\(s\)本质不同的回文串数量为\(q\),显然\(res-q\)肯定是\(2\)的倍数。求回文串数量是个板子题:here
- 因为\(s\)和\(rev(s)\)本质不同的公共子串除了回文串,就只有非回文串且\(x=rev(x)\)的串了。又因为\(x\)和\(rev(x)\)只能算一次贡献,所以最后答案就是\(all-\frac {res-q} 2\)。
- 所以我们现在只要能求出串\(t\)与串\(s\)的公共子串种类数量即可。(还有一种题是求长度至少为k的公共子串数量
做法2:
广义后缀自动机直接求即可。
用普通后缀自动机也有更简单做法,我在第一个做法下面有讲解。
做法3:
后缀数组
对一个串建后缀自动机,另一个串在上面跑同时计数
- 构建好\(s\)串的后缀自动机后,从根节点开始用\(t\)串在上面匹配,记录一下已经匹配的\(lcs\)长度\(LEN\)。若\(u\)节点有\(t[i]\)这个后继,则\(u\)跳到\(nex[u][t[i]-'a'],LEN++\);如果没有这个后继,就从\(u\)开始沿着后缀连接树向上走直到碰到一个节点\(x\)有\(t[i]\)这个后继或者到了根节点\(x\),则\(u = nex[x][t[i]-'a'],LEN=len[x]+1\)。
- 算贡献就是我当前在\(u\)节点,\(lcs\)长度为\(len\),那么\(LEN-len[link[u]]\)就是符合条件的子串。但是这不完全,就是如果\(len[link[u]]\)也大于\(0\)的话,那么他的父亲状态\(link[u]\)是有符合条件的子串,而且符合条件的子串的数量是固定的:\(len[u]-len[link[u]]\)。
- 听说如果你每次走后缀连接树算完所有贡献的话会\(tle\),一个优化就是匹配结束后,逆拓扑排序更新父亲结点的出现次数。像线段树一样用一个\(lazy\)标记记录它是否需要更新,要记得把\(lazy\)标记向父亲上传。
- 但是这样不够,因为还有一部分贡献没有计算,你可能多次匹配到自动机上的一个节点,我们需要记录一下匹配到每个节点的最长\(lcs\)长度即\(vis[u]\),若\(vis[u]\)等于\(0\),则贡献如上,反之贡献为\(LEN-vis[u]\),最后更新\(vis[u]\)为\(LEN\)。
- 本题结束。
其实还有一个更简单的方法,把串\(s\)和串\(rev(s)\)用一个没有出现过得字符拼接起来,求出新字符串的本质不同的子串个数\(x\),我们知道包含那个未出现过字符的子串数量为\(y = (Len+1)\times (Len+1)\),(注意串\((ba)\)和串\((ab)\)只能计一个贡献)然后在求出\(s\)本质不同的回文串个数\(p\),答案就是\(\frac{x-y+p}2\)
#pragma comment(linker, "/STACK:102400000,102400000")
#include<bits/stdc++.h>
#define fi first
#define se second
#define endl '\n'
#define o2(x) (x)*(x)
#define BASE_MAX 30
#define mk make_pair
#define eb emplace_back
#define all(x) (x).begin(), (x).end()
#define clr(a, b) memset((a),(b),sizeof((a)))
#define iis std::ios::sync_with_stdio(false); cin.tie(0)
#define my_unique(x) sort(all(x)),x.erase(unique(all(x)),x.end())
using namespace std;
#pragma optimize("-O3")
typedef long long LL;
typedef pair<int, int> pii;
inline LL read() {
LL x = 0;int f = 0;
char ch = getchar();
while (ch < '0' || ch > '9') f |= (ch == '-'), ch = getchar();
while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x = f ? -x : x;
}
inline void write(LL x) {
if (x == 0) {putchar('0'), putchar('\n');return;}
if (x < 0) {putchar('-');x = -x;}
static char s[23];
int l = 0;
while (x != 0)s[l++] = x % 10 + 48, x /= 10;
while (l)putchar(s[--l]);
putchar('\n');
}
int lowbit(int x) { return x & (-x); }
template<class T>T big(const T &a1, const T &a2) { return a1 > a2 ? a1 : a2; }
template<typename T, typename ...R>T big(const T &f, const R &...r) { return big(f, big(r...)); }
template<class T>T sml(const T &a1, const T &a2) { return a1 < a2 ? a1 : a2; }
template<typename T, typename ...R>T sml(const T &f, const R &...r) { return sml(f, sml(r...)); }
void debug_out() { cerr << '\n'; }
template<typename T, typename ...R>void debug_out(const T &f, const R &...r) {cerr << f << " ";debug_out(r...);}
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]: ", debug_out(__VA_ARGS__);
#define print(x) write(x);
const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;
const int HMOD[] = {1000000009, 1004535809};
const LL BASE[] = {1572872831, 1971536491};
const int mod = 998244353;
const int MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int MXN = 1e6 + 7;
int n;
char s[MXN], t[MXN];
LL all, ANS;
int vis[MXN], lazy[MXN];
struct Palindromic_Tree {
static const int MAXN = 600005 ;
static const int CHAR_N = 26 ;
int next[MAXN][CHAR_N];//next指针,next指针和字典树类似,指向的串为当前串两端加上同一个字符构成
int fail[MAXN];//fail指针,失配后跳转到fail指针指向的节点
int cnt[MAXN];
int num[MAXN];
int len[MAXN];//len[i]表示节点i表示的回文串的长度
int S[MAXN];//存放添加的字符
int last;//指向上一个字符所在的节点,方便下一次add
int n;//字符数组指针
int p;//节点指针
int pos[MAXN];
int newnode(int l) {//新建节点
for (int i = 0; i < CHAR_N; ++i) next[p][i] = 0;
cnt[p] = 0;
num[p] = 0;
len[p] = l;
return p++;
}
void init() {//初始化
p = 0;
newnode(0);
newnode(-1);
last = 0;
n = 0;
S[n] = -1;//开头放一个字符集中没有的字符,减少特判
fail[0] = 1;
}
int get_fail(int x) {//和KMP一样,失配后找一个尽量最长的
while (S[n - len[x] - 1] != S[n]) x = fail[x];
return x;
}
void add(int c, int id) {
c -= 'a';
S[++n] = c;
int cur = get_fail(last);//通过上一个回文串找这个回文串的匹配位置
if (!next[cur][c]) {//如果这个回文串没有出现过,说明出现了一个新的本质不同的回文串
int now = newnode(len[cur] + 2);//新建节点
fail[now] = next[get_fail(fail[cur])][c];//和AC自动机一样建立fail指针,以便失配后跳转
next[cur][c] = now;
num[now] = num[fail[now]] + 1;
}
last = next[cur][c];
cnt[last] ++;
pos[last] = id;
}
void count() {
for (int i = p - 1; i >= 0; --i) cnt[fail[i]] += cnt[i];
//父亲累加儿子的cnt,因为如果fail[v]=u,则u一定是v的子回文串!
}
} pt;
struct Suffix_Automaton {
static const int maxn = 1e6 + 105;
static const int MAXN = 1e6 + 5;
//basic
// map<char,int> nex[maxn * 2];
int nex[maxn*2][26];
int link[maxn * 2], len[maxn * 2];
int last, cnt;
LL tot_c;//不同串的个数
//extension
int cntA[MAXN * 2], A[MAXN * 2];/*辅助拓扑更新*/
int nums[MAXN * 2];/*每个节点代表的所有串的出现次数*/
void clear() {
tot_c = 0;
last = cnt = 1;
link[1] = len[1] = 0;
memset(nex[1], 0, sizeof(nex[1]));
}
void init_str(char *s) {
while (*s) {
add(*s - 'a');
++ s;
}
}
void add(int c) {
int p = last;
int np = ++cnt;
// nex[cnt].clear();
memset(nex[cnt], 0, sizeof(nex[cnt]));
len[np] = len[p] + 1;
last = np;
while (p && !nex[p][c])nex[p][c] = np, p = link[p];
if (!p)link[np] = 1, tot_c += len[np] - len[link[np]];
else {
int q = nex[p][c];
if (len[q] == len[p] + 1)link[np] = q, tot_c += len[np] - len[link[np]];
else {
int nq = ++cnt;
len[nq] = len[p] + 1;
// nex[nq] = nex[q];
memcpy(nex[nq], nex[q], sizeof(nex[q]));
link[nq] = link[q];
link[np] = link[q] = nq;
tot_c += len[np] - len[link[np]];
while (nex[p][c] == q)nex[p][c] = nq, p = link[p];
}
}
}
void build(int n) {
memset(cntA, 0, sizeof cntA);
memset(nums, 0, sizeof nums);
for (int i = 1; i <= cnt; i++)cntA[len[i]]++;
for (int i = 1; i <= n; i++)cntA[i] += cntA[i - 1];
for (int i = cnt; i >= 1; i--)A[cntA[len[i]]--] = i;
/*更行主串节点*/
int temps = 1;
for (int i = 0; i < n; i++) {
nums[temps = nex[temps][s[i] - 'a']] = 1;
}
for (int i = cnt, x; i >= 1; i--) {
x = A[i];
nums[link[x]] += nums[x];
}
}
void query() {
int u = 1, LEN = 0;
for(int i = 0; i < n; ++i) {
if(nex[u][t[i]-'a']) {
u = nex[u][t[i]-'a'];
++ LEN;
}else {
while (u && nex[u][t[i] - 'a'] == 0) u = link[u];
if (u == 0) u = 1, LEN = 0;
else {
LEN = len[u] + 1;
u = nex[u][t[i] - 'a'];
}
}
if(vis[u] == 0) {
ANS += 1 * (LEN - len[link[u]]);
// debug(i, t[i], LEN - len[link[u]])
if (len[link[u]]) lazy[link[u]] = 1;
vis[u] = LEN;
}else if(LEN > vis[u]) {
ANS += 1 * (LEN - vis[u]);
// debug(i, t[i], LEN - vis[u])
vis[u] = LEN;
}
}
for(int i = cnt, x; i >= 1; --i) {
x = A[i];
if(vis[x] == 0 && len[x] && lazy[x]) {
ANS += len[x] - len[link[x]];
vis[x] = len[x];
if(len[link[x]]) lazy[link[x]] = 1;
}else if(lazy[x] && vis[x] < len[x]) {
ANS += len[x] - vis[x];
vis[x] = len[x];
if(len[link[x]]) lazy[link[x]] = 1;
}
if(len[link[x]]) lazy[link[x]] = 1;
}
}
void DEBUG() {
for (int i = cnt; i >= 1; i--) {
printf("nums[%d]=%d numt[%d]=%d len[%d]=%d link[%d]=%d\n", i, nums[i], i, nums[i], i, len[i], i, link[i]);
}
}
} sam;
int main() {
#ifndef ONLINE_JUDGE
freopen("/home/cwolf9/CLionProjects/ccc/in.txt", "r", stdin);
//freopen("/home/cwolf9/CLionProjects/ccc/out.txt", "w", stdout);
#endif
// int tim = read();
scanf("%s", s);
memcpy(t, s, sizeof(s));
n = strlen(s);
reverse(t, t + n);
sam.clear();
sam.init_str(s);
all = sam.tot_c;
sam.build(n);
sam.query();
pt.init();
for(int i = 0; i < n; ++i) pt.add(s[i], i);
int hui = pt.p - 2;
debug(n, hui, all, ANS)
printf("%lld\n", all - (ANS - hui) / 2);
#ifndef ONLINE_JUDGE
cout << "time cost:" << clock() << "ms" << endl;
#endif
return 0;
}
广义后缀自动机
- 直接离线构建广义后缀自动机(插入函数和普通后缀自动机一模一样),先插入\(s\)串,置\(last=1\),再插入\(rev(s)\),然后对这个后缀自动机求出本质不同的子串个数\(all\)(回文串只计算一次贡献,其他串计算了两次,因为\(x=rev(x)\)),设\(p\)表示\(s\)串本质不同的回文串个数,最后答案即为\(\frac{all+p}2\)
后缀数组
其他:POJ 3415 求两个串长度至少为k的公共子串数量
本题不需要去重。可后缀数组也可后缀自动机写。
后缀自动机
解法和牛客那题基本一样,甚至更简单,因为本题不需要去重,是算总数。
不需要记录每个节点被匹配到的\(lcs\)长度,因此当前节点每次被匹配到的贡献都是\(LEN-max(len[link[u]],k-1)\)。
因为是算所有子串的数量,只需要用\(lazy[]\)标记表示这个节点被匹配到的次数,最后逆拓扑序向上传\(lazy[]\)标记即可。
后缀数组
按套路,把\(s,t\)拼成一个串,两遍单调栈,分别算\(t\)串对\(s\)串的贡献和\(s\)串对\(t\)串的贡献
#pragma comment(linker, "/STACK:102400000,102400000")
//#include<bits/stdc++.h>
#include<cstdio>
#include<cstring>
#include<string>
#include<vector>
#include<stack>
#include<map>
#include<iostream>
#include<assert.h>
#define fi first
#define se second
#define endl '\n'
#define o2(x) (x)*(x)
#define BASE_MAX 30
#define mk make_pair
#define eb emplace_back
#define all(x) (x).begin(), (x).end()
#define clr(a, b) memset((a),(b),sizeof((a)))
#define iis std::ios::sync_with_stdio(false); cin.tie(0)
#define my_unique(x) sort(all(x)),x.erase(unique(all(x)),x.end())
using namespace std;
#pragma optimize("-O3")
typedef long long LL;
typedef pair<int, int> pii;
inline LL read() {
LL x = 0;int f = 0;
char ch = getchar();
while (ch < '0' || ch > '9') f |= (ch == '-'), ch = getchar();
while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x = f ? -x : x;
}
inline void write(LL x) {
if (x == 0) {putchar('0'), putchar('\n');return;}
if (x < 0) {putchar('-');x = -x;}
static char s[23];
int l = 0;
while (x != 0)s[l++] = x % 10 + 48, x /= 10;
while (l)putchar(s[--l]);
putchar('\n');
}
int lowbit(int x) { return x & (-x); }
template<class T>T big(const T &a1, const T &a2) { return a1 > a2 ? a1 : a2; }
//template<typename T, typename ...R>T big(const T &f, const R &...r) { return big(f, big(r...)); }
//template<class T>T sml(const T &a1, const T &a2) { return a1 < a2 ? a1 : a2; }
//template<typename T, typename ...R>T sml(const T &f, const R &...r) { return sml(f, sml(r...)); }
//void debug_out() { cerr << '\n'; }
//template<typename T, typename ...R>void debug_out(const T &f, const R &...r) {cerr << f << " ";debug_out(r...);}
//#define debug(...) cerr << "[" << #__VA_ARGS__ << "]: ", debug_out(__VA_ARGS__);
#define print(x) write(x);
const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;
const int HMOD[] = {1000000009, 1004535809};
const LL BASE[] = {1572872831, 1971536491};
const int mod = 998244353;
const int MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int MXN = 2e5 + 7;
int n, m, k;
LL ANS;
char s[MXN], t[MXN];
LL lazy[MXN];
struct Suffix_Automaton {
static const int maxn = 2e5 + 105;
static const int MAXN = 2e5 + 5;
//basic
// map<char,int> nex[maxn * 2];
int nex[maxn][58];
int link[maxn * 2], len[maxn * 2];
int last, cnt;
LL tot_c;//不同串的个数
//extension
int cntA[MAXN * 2], A[MAXN * 2];/*辅助拓扑更新*/
int nums[MAXN * 2];/*每个节点代表的所有串的出现次数*/
void clear() {
tot_c = 0;
last = cnt = 1;
link[1] = len[1] = 0;
// nex[1].clear();
memset(nex[1], 0, sizeof(nex[1]));
}
void init_str(char *s) {
while (*s) {
add(*s - 'A');
++ s;
}
}
void add(int c) {
int p = last;
int np = ++cnt;
// nex[cnt].clear();
memset(nex[cnt], 0, sizeof(nex[cnt]));
len[np] = len[p] + 1;
last = np;
while (p && !nex[p][c])nex[p][c] = np, p = link[p];
if (!p)link[np] = 1, tot_c += len[np] - len[link[np]];
else {
int q = nex[p][c];
if (len[q] == len[p] + 1)link[np] = q, tot_c += len[np] - len[link[np]];
else {
int nq = ++cnt;
len[nq] = len[p] + 1;
// nex[nq] = nex[q];
memcpy(nex[nq], nex[q], sizeof(nex[q]));
link[nq] = link[q];
link[np] = link[q] = nq;
tot_c += len[np] - len[link[np]];
while (nex[p][c] == q)nex[p][c] = nq, p = link[p];
}
}
}
void build(int n) {
for(int i = 0; i <= cnt; ++i) nums[i] = cntA[i] = 0;
for (int i = 1; i <= cnt; i++) cntA[len[i]]++;
for (int i = 1; i <= n; i++)cntA[i] += cntA[i - 1];
for (int i = cnt; i >= 1; i--)A[cntA[len[i]]--] = i;
/*更行主串节点*/
int temps = 1;
for (int i = 0; i < n; i++) {
nums[temps = nex[temps][s[i] - 'A']] = 1;
}
for (int i = cnt, x; i >= 1; i--) {
x = A[i];
nums[link[x]] += nums[x];
}
}
void query() {
int u = 1, LEN = 0;
for(int i = 0; i < m; ++i) {
if(nex[u][t[i]-'A']) {
u = nex[u][t[i]-'A'];
++ LEN;
}else {
while (u && nex[u][t[i] - 'A'] == 0) u = link[u];
if (u == 0) u = 1, LEN = 0;
else {
LEN = len[u] + 1;
u = nex[u][t[i] - 'A'];
}
}
if(LEN >= k) {
ANS += (LL)nums[u] * (LEN - big(len[link[u]], k - 1));
if (len[link[u]]) lazy[link[u]] ++;
}
}
for(int i = cnt, x; i >= 1; --i) {
x = A[i];
if(len[x] >= k && lazy[x]) {
ANS += lazy[x] * nums[x] * (len[x] - big(len[link[x]], k - 1));
if(len[link[x]]) lazy[link[x]] += lazy[x];
}
}
}
void DEBUG() {
for (int i = cnt; i >= 1; i--) {
printf("nums[%d]=%d numt[%d]=%d len[%d]=%d link[%d]=%d\n", i, nums[i], i, nums[i], i, len[i], i, link[i]);
}
}
} sam;
int main() {
#ifndef ONLINE_JUDGE
freopen("/home/cwolf9/CLionProjects/ccc/in.txt", "r", stdin);
//freopen("/home/cwolf9/CLionProjects/ccc/out.txt", "w", stdout);
#endif
while(~scanf("%d", &k) && k) {
scanf("%s%s", s, t);
n = strlen(s), m = strlen(t);
sam.clear();
sam.init_str(s);
sam.build(n);
ANS = 0;
sam.query();
for(int i = 0; i <= 2 * n + 5; ++i) lazy[i] = 0;
printf("%lld\n", ANS);
}
#ifndef ONLINE_JUDGE
cout << "time cost:" << clock() << "ms" << endl;
#endif
return 0;
}
2019牛客多校第四场 I题 后缀自动机_后缀数组_求两个串de公共子串的种类数的更多相关文章
- 2019牛客多校第八场 F题 Flowers 计算几何+线段树
2019牛客多校第八场 F题 Flowers 先枚举出三角形内部的点D. 下面所说的旋转没有指明逆时针还是顺时针则是指逆时针旋转. 固定内部点的答案的获取 anti(A)anti(A)anti(A)或 ...
- 2019牛客多校第四场 A meeting
链接:https://ac.nowcoder.com/acm/contest/884/A来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 524288K,其他语言10485 ...
- 2019年牛客多校第四场 B题xor(线段树+线性基交)
题目链接 传送门 题意 给你\(n\)个基底,求\([l,r]\)内的每个基底是否都能异或出\(x\). 思路 线性基交板子题,但是一直没看懂咋求,先偷一份咖啡鸡板子写篇博客吧~ 线性基交学习博客:传 ...
- 2019牛客多校第四场B xor——线段树&&线性基的交
题意 给你 $n$ 个集合,每个集合中包含一些整数.我们说一个集合表示一个整数当且仅当存在一个子集其异或和等于这个整数.现在你需要回答 $m$ 次询问 ($l, r, x$),是否 $l$ 到 $r$ ...
- 2019牛客多校第四场J free——分层图&&最短路
题意 一张无向图,每条边有权值,可以选择不超过 $k$ 条路使其权值变成0,求 $S$ 到 $T$ 的最短路.(同洛谷 P4568) 分析 首先,分层图最短路可以有效解决这种带有 「阶段性」的最短路, ...
- 2019牛客多校第四场A meeting——树的直径
题意: 一颗 $n$ 个节点的树上标有 $k$ 个点,找一点使得到 $k$ 个关键结点的最大距离最小. 分析: 问题等价于求树的直径,最小距离即为直径除2向上取整. 有两种求法,一是动态规划,对于每个 ...
- [2019牛客多校第四场][G. Tree]
题目链接:https://ac.nowcoder.com/acm/contest/884/G 题目大意:给定一个树\(A\),再给出\(t\)次询问,问\(A\)中有多少连通子图与树\(B_i\)同构 ...
- 2019牛客多校第四场D-triples I 贪心
D-triples 题意 给你一个\(n\),问至少有几个数或运算起来可以等于\(n\),并且输出数量和这个几个数.题目说明给的\(n\)一定符合条件(不会输出\(n= 1\) 之类不存在情况). 思 ...
- 2019牛客多校第四场C-sequence(单调栈+线段树)
sequence 题目传送门 解题思路 用单调栈求出每个a[i]作为最小值的最大范围.对于每个a[i],我们都要乘以一个以a[i]为区间内最小值的对应的b的区间和s,如果a[i] > 0,则s要 ...
随机推荐
- flex布局滚动问题,子元素无法全部显示的解决办法
flex布局使用起来非常方便,对于水平垂直居中的需求,很容易就能实现.但是前不久,在做全屏弹窗遮罩登录的时候,遇到了flex布局滚动的一个问题,在此记录一下. 问题重现 理想情况下,当然是下面的状态, ...
- (转)Windows下zookeeper安装及配置
转:https://blog.csdn.net/qq_36332827/article/details/79700239 zookeeper有单机.伪集群.集群三种部署方式,可根据自己对可靠性的需求选 ...
- yii2和laravel比较
yii2和laravel比较 一.总结 一句话总结: 开发速度两者相当:laravel的artisan工具和yii的gii有异曲同工的效果,借助于artisan工具,可以快速创建控制器.模型和路由等. ...
- OpenCV2.4.8 + CUDA7.5 + VS2013 配置
配置过程主要参考:https://initialneil.wordpress.com/2014/09/25/opencv-2-4-9-cuda-6-5-visual-studio-2013/ 1.为什 ...
- spring boot 尚桂谷学习笔记05 ---Web
------web 开发登录功能------ 修改login.html文件:注意加粗部分为 msg 字符串不为空时候 才进行显示 <!DOCTYPE html> <!-- saved ...
- jmeter 线程组之间传递动态变化的变量值
http://www.51testing.com/html/01/n-3725501.html https://www.jianshu.com/p/73832bae65af https://blog. ...
- 【ARC076F】 Exhausted
hall定理大概是匈牙利的理论基础吧 hall定理的内容:二分图\(G\)的的左部点点集为\(\rm X\),右部点点集为\(\rm Y\),设\(|\rm X|\leq |Y|\),则二分图\(G\ ...
- 36.Minimum Path Sum(最小路径和)
Level: Medium 题目描述: Given a m x n grid filled with non-negative numbers, find a path from top left ...
- 【目录】mysql 架构篇系列
随笔分类 - mysql 架构篇系列 mysql 架构篇系列 4 复制架构一主一从搭建(半同步复制) 摘要: 一.概述 在mysql 5.5之前,mysql 的复制是异步操作,主库和从库的数据之间存在 ...
- Centos7 安装rar,unrar,zip,unzip
1.yum 安装unrar # yum install unrar rar命令 # rar a test.rar test.jpg test.png 这条命令是将test.jpg和test.png压缩 ...