KMP && Manacher && 扩展KMP整理
KMP算法:
kmp示例代码:
void cal_next(char *str, int *next, int len)
{
next[0] = -1;//next[0]初始化为-1,-1表示不存在相同的最大前缀和最大后缀
int k = -1;//k初始化为-1
for (int q = 1; q <= len-1; q++)
{
while (k > -1 && str[k + 1] != str[q])//如果下一个不同,那么k就变成next[k],注意next[k]是小于k的,无论k取任何值。
{
k = next[k];//往前回溯
}
if (str[k + 1] == str[q])//如果相同,k++
{
k = k + 1;
}
next[q] = k;//这个是把算的k的值(就是相同的最大前缀和最大后缀长)赋给next[q]
}
}
int KMP(char *str, int slen, char *ptr, int plen)
{
int *next = new int[plen];
cal_next(ptr, next, plen);//计算next数组
int k = -1;
for (int i = 0; i < slen; i++)
{
while (k >-1&& ptr[k + 1] != str[i])//ptr和str不匹配,且k>-1(表示ptr和str有部分匹配)
k = next[k];//往前回溯
if (ptr[k + 1] == str[i])
k = k + 1;
if (k == plen-1)//说明k移动到ptr的最末端
{
//cout << "在位置" << i-plen+1<< endl;
//k = -1;//重新初始化,寻找下一个
//i = i - plen + 1;//i定位到该位置,外层for循环i++可以继续找下一个(这里默认存在两个匹配字符串可以部分重叠),感谢评论中同学指出错误。
return i-plen+1;//返回相应的位置
}
}
return -1;
}
char *str = "bacbababadababacambabacaddababacasdsd";
char *ptr = "ababaca";
int a = KMP(str, 36, ptr, 7);
return 0;
kmp算法是用来找模式串是否在主串中出现,并返回第一次出现的位置。(模式串一般都比主串长度短,求的是模式串在主串中是否出现)
它有一个数组next[len](len是ptr字符串的长度),next[i]这里面放的是模式串的前i个字符的最长公共前后缀。(前缀不包括第i个字符)
时间复杂度:O(n+m)
算法过程:
你求的是模式串在主串中出现的位置,next[i]数组是模式串前i个字符的最长公共前后缀。
S1=abadfgag
S2=abac
next[0]=-1
next[1]=-1
next[2]=1
next[3]=-1
第一次匹配从S1第0位开始,得到S1[0,2]==S2[0,2]
那么下一次匹配还要从S1第1位开始吗?
不需要。kmp优化的就是这里,因为next[2]=1
那么就有S2[0]=S2[2],又因为S1[0,2]==S2[0,2]
所以S1[0]==S1[2],那么我们这次就可以直接从S1第3位开始匹配
例题:传送门
题意:
t组输入,给你一个模式串ptr,让你找出来它在str中出现的次数
题解:
利用KMP算法,只需要在kmp原来的基础上稍微改一下就可以用来求次数
1 #include<stdio.h>
2 #include<string.h>
3 #include<iostream>
4 #include<algorithm>
5 using namespace std;
6 const int maxn=1000005;
7 const int INF=0x3f3f3f3f;
8 char str[maxn],ptr[maxn];
9 int ans;
10 void get_next(int len,int *next)
11 {
12 next[0]=-1;
13 int k=-1;
14 for(int i=1;i<=len-1;++i)
15 {
16 while(k>-1 && ptr[k+1]!=ptr[i])
17 k=next[k];
18 if(ptr[k+1]==ptr[i])
19 {
20 k+=1;
21 }
22 next[i]=k;
23 }
24 }
25 void kmp(int slen,int plen)
26 {
27 int next[plen]; //这个next数组长度只能定义plen个长度,大的话会出错
28 get_next(plen,next);
29 int k=-1;
30 for(int i=0;i<slen;++i)
31 {
32 while(k>-1 && ptr[k+1]!=str[i])
33 {
34 k=next[k];
35 }
36 if(ptr[k+1]==str[i])
37 {
38 k=k+1;
39 }
40 if(k==plen-1)
41 {
42 ans++;
43 k=next[k];
44 //i=i-plen+1+1;
45 }
46 }
47 }
48 int main()
49 {
50 int t;
51 scanf("%d",&t);
52 while(t--)
53 {
54 ans=0;
55 scanf("%s%s",ptr,str);
56 int slen=strlen(str);
57 int plen=strlen(ptr);
58 kmp(slen,plen);
59 printf("%d\n",ans);
60 }
61 return 0;
62 }
有些题目利用next数组的特性来做,比如G - Seek the Name, Seek the Fame
这道题目需要找出来模式串中前后缀的所有相同长度,而不只是求最长
比如“alala”,它的最长相同前后缀是“ala”,但是还有“a”。等到把所有前后缀相同长度输出之后,再输出一下模式串长度就可以了。
1 #include<stdio.h>
2 #include<string.h>
3 #include<iostream>
4 #include<algorithm>
5 using namespace std;
6 const int maxn=400005;
7 const int INF=0x3f3f3f3f;
8 char ptr[maxn];
9 int w[maxn];
10 void get_next(int len,int *next)
11 {
12 next[0]=-1;
13 int k=-1;
14 for(int i=1;i<=len-1;++i)
15 {
16 while(k>-1 && ptr[k+1]!=ptr[i])
17 k=next[k];
18 if(ptr[k+1]==ptr[i])
19 {
20 k+=1;
21 }
22 next[i]=k;
23 }
24 }
25 int main()
26 {
27 int n;
28 while(~scanf("%s",ptr))
29 {
30 int len=strlen(ptr);
31 int next[len];
32 get_next(len,next);
33 int g=0,k=next[len-1];
34 //w[g++]=next[len-1]+1;
35 while(k>=0)
36 {
37 w[g++]=k+1;
38 k=next[k];
39
40 }
41 sort(w,w+g);
42 for(int i=0;i<g;++i)
43 if(w[i]!=w[i-1] && i!=0)
44 printf("%d ",w[i]);
45 else if(i==0) printf("%d ",w[i]);
46 printf("%d\n",len);
47 }
48 return 0;
49 }
扩展kmp:
扩展KMP求的是对于原串S1的每一个后缀子串与模式串S2的最长公共前缀。它有一个next[]数组和一个extend[]数组。
next[i]表示为模式串S2中以i为起点的后缀字符串和模式串S2的最长公共前缀长度.
extend[i]表示为以字符串S1中以i为起点的后缀字符串和模式串S2的最长公共前缀长度.
复杂度:拓展kmp算法的总体复杂度为O(n+m)的。其中n为母串的长度,m为子串的长度。
算法过程:
S2=aaaaab
第一步,我们先对原串S1和模式串S2进行逐一匹配,直到发生不配对的情况。我们可以看到,S1[0]=S2[0],S1[1]=S2[1],S1[2]=S2[2],S1[3] ≠S2[3],此时匹配失败,第一步结束,我们得到S1[0,2]=S2[0,2],即extend[0]=3;
给出n组询问,每一组询问包含两个字符串t s,问s中是否包含t。(t中有’?’,’?’可以代替任何字符)。
1 #include<iostream>
2 #include<cstring>
3 #include<cstdio>
4 #include<string>
5 #include<algorithm>
6 using namespace std;
7 int l1,l2,n;
8 char s[100009],t[100009];
9 int nxt[100009];
10 void next_make()
11 {
12 int t1=0,t2=-1;
13 nxt[0]=-1;
14 while(t1<l1)
15 {
16 if(t2==-1||t[t1]==t[t2]||t[t2]=='?') nxt[++t1]=++t2;
17 else t2=nxt[t2];
18 }
19 }
20 void match(int t1,int t2)
21 {
22 while(t1<l1&&t2<l2)
23 {
24 if(t1==-1||t[t1]==s[t2]||t[t1]=='?') t1++,t2++;
25 else t1=nxt[t1];
26 }
27 if(t1==l1) printf("God bless You!\n");
28 else printf("Game Over!\n");
29 return;
30 }
31 int main()
32 {
33 scanf("%d",&n);
34 while(n--)
35 {
36 cin>>t;cin>>s;
37 l1=strlen(t);
38 l2=strlen(s);
39 next_make();
40 match(0,0);
41 }
42 return 0;
43 }
例题:给一堆字符串,求最长公共字串。
找一个最短的串,暴力求出每一个后缀,和所有串匹配,找到每个extend里最大的,取总体最小,是一个答案,找到所有答案里长度最长的字典序最小的,就是答案。
1 #define ll long long
2 #define db double
3 #define ioss ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
4 using namespace std;
5 int n,cnt;
6 ll ext[220],nex[220];
7 string skr[4020];
8 string ans[4020];
9 void getNext(string &strp,ll nextt[])
10 {
11 ll pl=strp.size();
12 ll fir=0,las=0;
13 nextt[0]=pl;
14 for(ll i=1; i<pl; i++)
15 {
16 nextt[i] = min(las - i + 1, nextt[i - fir]);
17 if (nextt[i] < 0) nextt[i] = 0;
18 while (i+nextt[i]<pl && strp[nextt[i]] == strp[i + nextt[i]])
19 {
20 nextt[i]++;
21 }
22 if (i + nextt[i] - 1 > las)
23 {
24 las = i + nextt[i] - 1;
25 fir = i;
26 }
27 }
28 }
29 void exKMP(string &strp,string &strs,ll nextt[],ll extt[])
30 {
31 getNext(strp,nextt);
32 ll pl=strp.size(),sl=strs.size();
33 ll fir=0,las=-1,mnl=min(sl,pl);
34 while(las<mnl-1&&strp[las+1]==strs[las+1])
35 {
36 las++;
37 }
38 extt[0]=las+1;
39 for(ll i=1; i<sl; i++)
40 {
41 extt[i]=min(las-i+1,nextt[i-fir]);
42 if(extt[i]<0) extt[i]=0;
43 while(extt[i]<pl && i+extt[i]<sl && strp[extt[i]]==strs[i+extt[i]])
44 {
45 extt[i]++;
46 }
47 if(i+extt[i]-1>las)
48 {
49 las=i+extt[i]-1;
50 fir=i;
51 }
52 }
53 }
54 int main()
55 {
56 while(scanf("%d",&n)==1&&n)
57 {
58 cnt=0;
59 int mnlen=300,mnlenx;
60 for(int i=1; i<=n; i++)
61 {
62 cin >> skr[i];
63 if (skr[i].size() < mnlen)
64 {
65 mnlen = skr[i].size();
66 mnlenx = i;
67 }
68 }
69 for(int i=0; i<skr[mnlenx].size(); i++)
70 {
71 ll mn=1e10;
72 string cur=skr[mnlenx].substr(i);
73 for(int j=1; j<=n; j++)
74 {
75 ll mx=0;
76 exKMP(cur,skr[j],nex,ext);
77 for(int k=0; k<skr[j].size(); k++)
78 {
79 mx=max(mx,ext[k]);
80 }
81 mn=min(mn,mx);
82 }
83 if(mn>0)
84 {
85 if(cnt==0||(mn==ans[1].size()))
86 {
87 ans[++cnt]=cur.substr(0,mn);
88 }
89 else if(mn>ans[1].size())
90 {
91 cnt=0;
92 ans[++cnt]=cur.substr(0,mn);
93 }
94 }
95 }
96 if(cnt)
97 {
98 sort(ans+1,ans+1+cnt);
99 cout<<ans[1]<<endl;
100 }
101 else cout<<"IDENTITY LOST"<<endl;
102 }
103 return 0;
104 }
Manacher算法:
当我们遇到字符串为“aaaaaaaaa”,之前的算法就会发生各个回文相互重叠的情况,会产生重复计算,然后就产生了一个问题,能否改进?答案是能,1975年,一个叫Manacher发明了Manacher Algorithm算法,俗称马拉车算法,其时间复杂为O(n)。
例题:
给你一个字符串(仅含字母),每个字母有一个价值,把字符串切断成两部分,若其中一部分为回文串,则其价值等于各字母价值和相加;否则为0。总价值为两部分价值相加,求最大价值。
题解:
先用manacher求出回文子串长度,再枚举切割点,若切后子串的中点是回文中心,且回文长度扩展到i点,则这个子串为回文,记录价值。最后输出最大价值。
代码:
1 #include<stdio.h>
2 #include<string.h>
3 #include<iostream>
4 #include<queue>
5 #include<algorithm>
6 using namespace std;
7 const int maxn=5e5+10;
8 char str[maxn*2],s[maxn];
9 int len,Len[maxn*2],val[maxn],v[30];
10 void init()
11 {
12 memset(str,0,sizeof(str));
13 int k=0;
14 str[k++]='$';
15 for(int i=1;i<=len;++i)
16 {
17 str[k++]='#';
18 str[k++]=s[i];
19 }
20 str[k++]='#';
21 len=k;
22 }
23 void manacher()
24 {
25 Len[0]=0;
26 int sum=0;
27 int id,mx=0;
28 for(int i=1;i<len;++i)
29 {
30 if(i<mx) Len[i]=min(mx-i,Len[2*id-i]);
31 else Len[i]=1;
32 while(str[i-Len[i]]==str[i+Len[i]]) Len[i]++;
33 if(Len[i]+i>mx)
34 {
35 mx=Len[i]+i;
36 id=i;
37 }
38 }
39 }
40 int main()
41 {
42 int t;
43 scanf("%d",&t);
44 while(t--)
45 {
46 for(int i=0;i<26;++i)
47 scanf("%d",&v[i]);
48 scanf("%s",s+1);
49 len=strlen(s+1);
50 for(int i=1;i<=len;++i)
51 {
52 val[i]=val[i-1]+v[s[i]-'a'];
53 }
54 int n=len;
55 init();
56 manacher();
57 int ans=0;
58 for(int i = 1; i < n; i++){
59 int tmp = 0;
60 if(Len[i + 1] - 1 == i){
61 if(i % 2){
62 tmp += val[i / 2] * 2 + v[s[(i + 1) / 2] - 'a'];
63 }
64 else{
65 tmp += val[i / 2] * 2;
66 }
67 }
68 if(Len[i + n + 1] - 1 == n - i){
69 if((n - i) % 2){
70 tmp += (val[i + (n - i) / 2] - val[i]) * 2 + v[s[i + (n + 1- i) / 2] - 'a'];
71 }
72 else{
73 tmp += (val[i + (n - i) / 2] - val[i]) * 2;
74 }
75 }
76 ans = max(ans, tmp);
77 }
78 printf("%d\n",ans);
79 }
80 return 0;
81 }
板子:
1 /* 这是一个板子
2 #include<iostream>
3 #include<string>
4 #include<cstring>
5 #include<algorithm>
6 #include<vector>
7 #include<cmath>
8 using namespace std;
9 //算法主体
10 int maxLcsplength(string str) {
11 //空字符串直接返回0
12 if (str.length() == 0) {
13 return 0;
14 }
15 //记录下manacher字符串的长度,方便后面使用
16 int len = (int)(str.length() * 2 + 1);
17 //开辟动态数组chaArr记录manacher化的字符串
18 //开辟动态数组pArr记录每个位置的回文半径
19 char *chaArr = new char[len];
20 int* pArr = new int[len];
21 int index = 0;
22 for (int i = 0; i < len;i++) {
23 chaArr[i] = (i & 1) == 0 ? '#' : str[index++];
24 }
25 //到此完成对原字符串的manacher化
26 //R是最右回文边界,C是R对应的最左回文中心,maxn是记录的最大回文半径
27 int R = -1;
28 int C = -1;
29 int maxn = 0;
30 //开始从左到右遍历
31 for (int i = 0; i < len; i++) {
32 //第一步直接取得可能的最短的回文半径,当i>R时,最短的回文半径是1,反之,最短的回文半径可能是i对应的i'的回文半径或者i到R的距离
33 pArr[i] = R > i ? min(R - i, pArr[2 * C - i]) : 1;
34 //取最小值后开始从边界暴力匹配,匹配失败就直接退出
35 while (i + pArr[i]<len && i - pArr[i]>-1) {
36 if (chaArr[i + pArr[i]] == chaArr[i - pArr[i]]) {
37 pArr[i]++;
38 }
39 else {
40 break;
41 }
42 }
43 //观察此时R和C是否能够更新
44 if (i + pArr[i] > R) {
45 R = i + pArr[i];
46 C = i;
47 }
48 //更新最大回文半径的值
49 maxn = max(maxn, pArr[i]);
50 }
51 //记得清空动态数组哦
52 delete[] chaArr;
53 delete[] pArr;
54 //这里解释一下为什么返回值是maxn-1,因为manacherstring的长度和原字符串不同,所以这里得到的最大回文半径其实是原字符串的最大回文子串长度加1,有兴趣的可以自己验证试试
55 return maxn - 1;
56 }
57 int main()
58 {
59 string s1 = "";
60 cout << maxLcsplength(s1) << endl;
61 string s2 = "abbbca";
62 cout << maxLcsplength(s2) << endl;
63 return 0;
64 }
65 */
66
67
68 /*
69 #include<stdio.h>
70 #include<string.h>
71 #include<iostream>
72 #include<queue>
73 #include<algorithm>
74 using namespace std;
75 const int maxn=5e5+10;
76 char str[maxn*2],s[maxn];
77 int len,Len[maxn*2],val[maxn],v[30];
78 void init()
79 {
80 memset(str,0,sizeof(str));
81 int k=0;
82 str[k++]='$';
83 for(int i=1;i<=len;++i)
84 {
85 str[k++]='#';
86 str[k++]=s[i];
87 }
88 str[k++]='#';
89 len=k;
90 }
91 void manacher()
92 {
93 Len[0]=0;
94 int sum=0;
95 int id,mx=0;
96 for(int i=1;i<len;++i)
97 {
98 if(i<mx) Len[i]=min(mx-i,Len[2*id-i]);
99 else Len[i]=1;
100 while(str[i-Len[i]]==str[i+Len[i]]) Len[i]++;
101 if(Len[i]+i>mx)
102 {
103 mx=Len[i]+i;
104 id=i;
105 }
106 }
107 }
108 int main()
109 {
110 int t;
111 scanf("%d",&t);
112 while(t--)
113 {
114 for(int i=0;i<26;++i)
115 scanf("%d",&v[i]);
116 scanf("%s",s+1);
117 len=strlen(s+1); //3
118
119 //printf("%d**\n",len); //3
120 //init();
121 //manacher();
122 //printf("%d**\n",len); //8,这个是字符串处理完之后的长度
123 //for(int i=0;i<=len;++i){
124 // printf("%d %d\n",i,Len[i]);
125 //}
126
127
128 for(int i=1;i<=len;++i)
129 {
130 val[i]=val[i-1]+v[s[i]-'a'];
131 }
132 int n=len;
133 init();
134 manacher();
135 int ans=0;
136 for(int i = 1; i < n; i++){
137 int tmp = 0;
138 if(Len[i + 1] - 1 == i){
139 if(i % 2){
140 tmp += val[i / 2] * 2 + v[s[(i + 1) / 2] - 'a'];
141 }
142 else{
143 tmp += val[i / 2] * 2;
144 }
145 }
146 if(Len[i + n + 1] - 1 == n - i){
147 if((n - i) % 2){
148 tmp += (val[i + (n - i) / 2] - val[i]) * 2 + v[s[i + (n + 1- i) / 2] - 'a'];
149 }
150 else{
151 tmp += (val[i + (n - i) / 2] - val[i]) * 2;
152 }
153 }
154 ans = max(ans, tmp);
155 }
156 printf("%d\n",ans);
157
158 }
159 return 0;
160 }
161 */
162
163
164
165 /*
166
167 #include <cstdio>
168
169 #include <cmath>
170
171 #include <cstring>
172
173 #include <cstdlib>
174
175 #include <iostream>
176
177 #include <algorithm>
178
179 #include <queue>
180
181 #include <stack>
182
183 using namespace std;
184
185 char a[51000005];
186
187 char s[102000005];
188
189 int p[51000005];
190
191 int maxp,p0,l;
192
193 int ans=1;
194
195 void manacher()
196
197 {
198
199 for(int i=1;i<l;i++)
200
201 {
202
203 if(i<maxp)
204
205 {
206
207 int j=(p0<<1)-i;
208
209 p[i]=min(p[j],p[p0]+p0-i);
210
211 }else
212
213 {
214
215 p[i]=1;
216
217 }
218
219 while(s[i-p[i]]==s[i+p[i]])
220
221 {
222
223 p[i]++;
224
225 }
226
227 if(i+p[i]>maxp)
228
229 {
230
231 p0=i;
232
233 maxp=i+p[i];
234
235 }
236
237 }
238
239 }
240
241 int main()
242
243 {
244
245 scanf("%s",a+1);
246
247 l=strlen(a+1);
248
249 p[1]=1;
250
251 s[0]=s[1]='#';
252
253 for(int i=1;i<=l;i++)
254
255 {
256
257 s[2*i]=a[i];
258
259 s[2*i+1]='#';
260
261 }
262
263 l=(l<<1)+2;
264
265 s[l]='0';
266
267 manacher();
268
269 for(int i=1;i<=l;i++)
270
271 {
272
273 ans=max(ans,p[i]-1);
274
275 }
276
277 printf("%d\n",ans);
278
279 return 0;
280
281 }
282
283 */ 板子
KMP && Manacher && 扩展KMP整理的更多相关文章
- Manacher模板,kmp,扩展kmp,最小表示法模板
*N]; //储存临时串 *N];//中间记录 int Manacher(char tmp[]) { int len=strlen(tmp); ; ;i<len;i++) { s[cnt++]= ...
- KMP和扩展KMP【转】
这种东西基本上在纸上自己推导一下就能做出来XD 转发注明出处 KMP 给出两个字符串A(称为模板串)和B(称为子串),长度分别为lenA和lenB,要求在线性时间内,对于每个A[i] (0<=i ...
- KMP与扩展KMP
原文转自:http://www.cppblog.com/MatoNo1/archive/2011/04/17/144390.aspx KMP:给出两个字符串A(称为模板串)和B(称为子串),长度分别为 ...
- KMP 、扩展KMP、Manacher算法 总结
一. KMP 1 找字符串x是否存在于y串中,或者存在了几次 HDU1711 Number Sequence HDU1686 Oulipo HDU2087 剪花布条 2.求多个字符串的最长公共子串 P ...
- 666 专题三 KMP & 扩展KMP & Manacher
KMP: Problem A.Number Sequence d.求子串首次出现在主串中的位置 s. c. #include<iostream> #include<stdio.h&g ...
- KMP和扩展KMP
文章网上太多这里提一下代码细节: KMP: scanf("%s\n",s); scanf("%s\n",t); int ls=strlen(s),lt=strl ...
- kmp模板 && 扩展kmp模板
kmp模板: #include <bits/stdc++.h> #define PB push_back #define MP make_pair using namespace std; ...
- 【kmp或扩展kmp】HDU 6153 A Secret
acm.hdu.edu.cn/showproblem.php?pid=6153 [题意] 给定字符串A和B,求B的所有后缀在A中出现次数与其长度的乘积之和 A和B的长度最大为1e6 方法一:扩展kmp ...
- kmp与扩展kmp模板
kmp 1 #include <algorithm> 2 #include <iostream> 3 #include <cstring> 4 #include & ...
随机推荐
- TCP/IP五层模型-应用层-DNS协议
1.定义:域名解析协议,把域名解析成对应的IP地址. 2.分类:①迭代解析:DNS所在服务器若没有可以响应的结果,会向客户机提供其他能够解析查询请求的DNS服务器地址,当客户机发送查询请求时,DNS ...
- 【Java】Jsoup爬虫,一个简单获取京东商品信息的小Demo
简单记录 - Jsoup爬虫入门实战 数据问题?数据库获取,消息队列中获取中,都可以成为数据源,爬虫! 爬取数据:(获取请求返回的页面信息,筛选出我们想要的数据就可以了!) 我们经常需要分析HTML网 ...
- 【Oracle】将数据库设为开机自启
由于某些特殊条件,需要将oracle数据库设置为开机自己,其实很简单 环境:oracle10gR2 1.修改/etc/oratab # This file is used by ORACLE util ...
- LeetCode872. 叶子相似的树
题目 1 class Solution { 2 public: 3 vector<int>ans1; 4 vector<int>ans2; 5 bool leafSimilar ...
- uni-app开发经验分享九: 组件传值
一.父组件向子组件传值 通过props来实现,子组件通过props来接收父组件传过来的值! 1.逻辑梳理 父组件中: 第一步:引入子组件: import sonShow from '../../com ...
- Dubbo 最基本的几个需求
需求 http://dubbo.apache.org/zh-cn/docs/user/preface/requirements.html 在大规模服务化之前,应用可能只是通过 RMI 或 Hessia ...
- Linux下nf_conntrack(最全面)_董明磊-CSDN博客_nf_conntrack https://blog.csdn.net/qq_35299863/article/details/79530732
Linux下nf_conntrack(最全面)_董明磊-CSDN博客_nf_conntrack https://blog.csdn.net/qq_35299863/article/details/79 ...
- OpenSSL 常见对称加密算法特性分析
在选择加密算法,面对一大长串的选项时,大家都有这样的疑问,究竟哪种加密方式是最好的呢? 对于加密方式.算法来说,一般安全性与性能呈负相关,越是安全的,对性能要求则更高. 现在主流的加密协议的安全性均能 ...
- 切片声明 切片在内存中的组织方式 reslice
数组是具有相同 唯一类型 的一组已编号且长度固定的数据项序列(这是一种同构的数据结构),[5]int和[10]int是属于不同类型的.数组的编译时值初始化是按照数组顺序完成的(如下). 切片声明方式, ...
- forEach、for in、for of三者区别
forEach更多的用来遍历数组for in 一般常用来遍历对象或jsonfor of数组对象都可以遍历,遍历对象需要通过和Object.keys()for in循环出的是key,for of循环出的 ...