[学习笔记] hash & kmp & Trie树 - 字符串
Hash
Oulipo
没啥好说的,进制hash板子。
#include<bits/stdc++.h>
using namespace std;
#define ull unsigned long long
const int N = 1e6 + 1;
int n, lw, lt, ans;
ull hw, ht[N], p[N];
inline ull gethash(int l, int r){ return ht[r] - ht[l] * p[r - l]; }
inline void wt(int k){ if(k/10) wt(k/10); putchar(k%10+'0'); }
int main(){
p[0] = 1;
for(int i=1; i<=N; ++i) p[i] = p[i-1] * 131;
char ch = getchar();
while(isdigit(ch)) n = (n<<1) + (n<<3) + (ch^48), ch = getchar();
while(n--){
ans = hw = lt = lw = 0;
char ch = getchar();
while(ch < 'A' || ch > 'Z') ch = getchar();
while(ch >= 'A' && ch <= 'Z') hw = hw * p[1] + ch, ++lw, ch = getchar();
while(ch < 'A' || ch > 'Z') ch = getchar();
while(ch >= 'A' && ch <= 'Z' && ++lt){
ht[lt] = ht[lt-1] * p[1] + ch;
ch = getchar();
if(lt >= lw) if(gethash(lt-lw, lt) == hw) ++ans;
} wt(ans), putchar('\n');
} return 0;
}
[USACO17OPEN] Bovine Genomics S
简单来说,存在某一区间使得任意A串与B串都不相等,现在要找这一区间的最小值。进制哈希之后,可以暴力判断某一长度区间是否合法。再加上区间长度和其合法性是有单调关系的(随着区间长度越小,就越不可能合法),所以再加上二分即可
#include<bits/stdc++.h>
using namespace std;
#define ull unsigned long long
int n, m, ans;
ull ha[501][501], hb[501][501], p[501];
string A[501], B[501];
inline void Hash(string str, ull *h){
for(int i=0; i<m; ++i)
h[i+1] = h[i] * p[1] + str[i] - 'A';
}
inline ull gethash(int l, int r, ull *h){ return h[r] - h[l] * p[r-l]; }
inline bool check(int len){ //暴力判断
for(int k=len; k<=m; ++k){
bool data = 0;
for(int i=1; i<=n; ++i)
for(int j=1; j<=n; ++j)
if(gethash(k-len, k, ha[i]) == gethash(k-len, k, hb[j])) data = 1;
if(!data) return 1;
} return 0;
}
int main(){
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
p[0] = 1;
for(int i=1; i<=500; ++i) p[i] = p[i-1] * 131;
cin>>n>>m;
for(int i=1; i<=n; ++i) cin>>A[i], Hash(A[i], ha[i]);
for(int i=1; i<=n; ++i) cin>>B[i], Hash(B[i], hb[i]);
int l = 1, r = m;
while(l < r){
int mid = (l + r) >> 1;
if(check(mid)) r = mid;
else l = mid+1;
} return cout<<l, 0;
}
P4591 [TJOI2018] 碱基序列
hash + 分组背包
dp[i][j]
表示第 \(i\) 组氨基酸放到蛋白质的第 \(j\) 个位置的方案数。同样是每一组只取一种物品放入背包,就可以类比于分组背包。len_z
表示第 \(z\) 个氨基酸的长度,于是有转移方程(转移时记得判断是否能配对上):
\]
#include<bits/stdc++.h>
using namespace std;
#define ull unsigned long long
int n, num[101], ls, lp[101][11], dp[10001], mod = 1e9 + 7, ans;
string s;
ull h[101][11], hs[10001], p[10001];
inline ull gethash(int l, int r){ return hs[r] - hs[l] * p[r-l]; }
int main(){
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin>>n>>s;
p[0] = 1; for(int i=1; i<=n; ++i) p[i] = p[i-1] * 131;
ls = s.size();
for(int i=0; i<ls; ++i) hs[i+1] = hs[i] * p[1] + s[i];
for(int i=1; i<=n; ++i){
cin>>num[i];
string str;
for(int j=1; j<=num[i]; ++j){
cin>>str;
lp[i][j] = str.size();
for(int z=0; z<lp[i][j]; ++z) h[i][j] = h[i][j] * p[1] + str[z];
}
}
for(int i=0; i<=ls; ++i) dp[i] = 1; //注意从0开始
for(int i=1; i<=n; ++i)
for(int k=ls; k>=0; --k){//注意要把dp[0]也更新一下
dp[k] = 0;
for(int j=1; j<=num[i]; ++j)
if(k >= lp[i][j] && gethash(k-lp[i][j], k) == h[i][j]) dp[k] = (dp[k] + dp[k - lp[i][j]]) % mod;
if(i == n) ans = (ans + dp[k]) % mod;
} return cout<<ans, 0;
}
[CQOI2014] 通配符匹配
#include<bits/stdc++.h>
using namespace std;
#define ull unsigned long long
#define bl (gethash(j-id[i]+id[i-1], j-1, hp) == gethash(id[i-1], id[i]-1, hs))
const int N = 1e5 + 5;
ull hs[N], p[N], hp[N];
string s, st;
int ls, id[15], n, len, cnt, dp[15][N];
inline ull gethash(int l, int r, ull *h){ return h[r] - h[l] * p[r-l]; }
int main(){
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
p[0] = 1; for(int i=1; i<N; ++i) p[i] = p[i-1] * (ull)131;
cin>>s; s += '?';
ls = s.size();
for(int i=1; i<=ls; ++i){
hs[i] = hs[i-1] * p[1] + s[i-1];
if(s[i-1] == '?' || s[i-1] == '*') id[++cnt] = i;
}
cin>>n;
while(n--){
memset(dp, 0, sizeof dp);
cin>>st; st += 'a';
len = st.size();
for(int i=1; i<=len; ++i) hp[i] = hp[i-1] * p[1] + st[i-1];
dp[0][0] = 1;
for(int i=1; i<=cnt; ++i) for(int j=id[i]-id[i-1]; j<=len; ++j){
if(dp[i][j-1] == 2){ dp[i][j] = 2; continue; }
if(!dp[i-1][j - id[i] + id[i-1]] || !bl) continue;
if(s[id[i]-1] == '?') dp[i][j] = 1;
else dp[i][j] = dp[i][j-1] = 2;
}
if(dp[cnt][len]) cout<<"YES\n";
else cout<<"NO\n";
} return 0;
}
[NOI2017] 蚯蚓排队
上面的内容都只是用hash来映射字符串,但如果要映射数字或者其他数据类型就需要用到哈希表。5分钟搞定哈希表。哈希表要比map快的多。
对于本题来说,需要完成以下三个操作:
- 合并队伍:这个很好实现,直接用链表模拟即可。用两个数组分别表示某一个蚯蚓的前驱和后继。我们注意到,数据范围中 \(k\) 非常小,不妨考虑暴力统计每一次合并时新产生的字符串。可以将新产生的字符串映射成哈希,接着用哈希表统计该字符串的数量即可。
- 分离队伍:同样用链表实现,统计每次分开时消失的字符串,并在哈希表中将数量-1即可。
- 统计个数:将字符串 \(s\) 映射成哈希,并在哈希表里统计个数即可。
一般来说,在哈希表中链表越长,搜索效率越差。所以为了提高效率,哈希表开成尽量大的素数。我用的 10000019
。
#include<bits/stdc++.h>
using namespace std;
#define ull unsigned long long
#define ll long long
const int N = 2e5 + 2, hmod = 10000019, hmax = 1e7 + 5;
const ll mod = 998244353;
int n, m, dt, a, b, nxt[N], lst[N], k;
ull p[N], hs[N], f[N];
string s;
struct Hash_table{
int cnt, head[hmod+1], nxt[hmax]; ull val[hmax]; ll num[hmax];
inline void add(ull h, int v){
int tb = h % hmod;
for(int i=head[tb]; i; i=nxt[i])
if(val[i] == h){ num[i] = num[i] + v; return; }
val[++cnt] = h, ++num[cnt], nxt[cnt] = head[tb], head[tb] = cnt;
}
inline ll query(ull h){
int tb = h % hmod;
for(int i=head[tb]; i; i=nxt[i])
if(val[i] == h) return num[i];
return 0ll;
}
} Hash;
inline int rd(){
int x = 0; char ch = getchar();
while(!isdigit(ch)) ch = getchar();
while(isdigit(ch)) x = (x<<1) + (x<<3) + (ch^48), ch = getchar();
return x;
}
inline string rds(){
string str = ""; char ch = getchar();
while(ch != ' ') str += ch, ch = getchar();
return str;
}
inline void wt(ll k){ if(k/10) wt(k/10); putchar(k%10+'0'); }
inline ull gethash(int l, int r){ return hs[r]-hs[l]*p[r-l]; }
inline void add(int a, int b){
nxt[a] = b, lst[b] = a;
ull nhash = 0, mhash;
for(int i=a, la=1; i&&la<=50; i=lst[i], ++la){
nhash += f[i]*p[la-1], mhash = nhash;
for(int j=b, lb=la+1; j&&lb<=50; j=nxt[j], ++lb){
mhash = mhash * p[1] + f[j];
Hash.add(mhash, 1);
}
}
}
inline void divide(int a){
int b = nxt[a]; ull nhash = 0, mhash;
for(int i=a, la=1; i&&la<=50; i=lst[i], ++la){
nhash += f[i]*p[la-1], mhash = nhash;
for(int j=b, lb=la+1; j&&lb<=50; j=nxt[j], ++lb){
mhash = mhash * p[1] + f[j];
Hash.add(mhash, -1);
}
}
nxt[a] = lst[b] = 0;
}
inline ll query(int k){
int len = s.size(); ll ans = 1;
for(int i=1; i<=len; ++i) hs[i] = hs[i-1]*p[1] + s[i-1] - '0';
for(int i=k; i<=len; ++i){
ull nhash = gethash(i-k, i);
ans = (__int128)ans * Hash.query(nhash) % mod;
} return ans;
}
int main(){
n=rd(), m=rd(); p[0] = 1;
for(int i=1; i<=N; ++i) p[i] = p[i-1] * 131;
for(int i=1; i<=n; ++i) f[i] = rd(), Hash.add(f[i], 1);
while(m-- && (dt=rd())){
if(dt == 1) a=rd(), b=rd(), add(a, b);
if(dt == 2) a=rd(), divide(a);
if(dt == 3) s=rds(), k=rd(), wt(query(k)), putchar('\n');
} return 0;
}
kmp
[POJ 2752] Seek the Name, Seek the Fame
这道题纯纯是考Next数组的。对于一个串来说,它的第一长公共前后缀肯定是他自己,第二就是 \(Next[s.len]\) ,第三就是 \(Next[Next[s.len]]\) 以此类推。在这道题里仅需递推求出所有Next值即可。
#include<bits/stdc++.h>
using namespace std;
const int N = 4e5 + 1; string s; int Next[N];
inline void getans(int k){
if(!k) return;
getans(Next[k]), cout<<k<<' ';
}
inline void getnext(){
int len = s.size(), j = 0;
Next[0] = Next[1] = 0;
for(int i=1; i < len; ++i, j=Next[i]){
while(j && s[i] != s[j]) j = Next[j];
if(s[i] == s[j]) Next[i+1] = j+1;
else Next[i+1] = 0;
} getans(j), cout<<len<<'\n';
}
int main(){
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
while(cin>>s) getnext(); return 0;
}
[NOI2014] 动物园
这道题是上道题的进阶版本,加深了我对kmp求next数组的思想运用。我们知道,Next[i]
是一个字符串里最长前缀后缀的长度,计算num
数组其实只需要判断最长前后缀的长度和原字符串的长度即可。思路简单,但问题在于复杂度。这道题的思想和kmp思想是一样的,使用双指针,固定 \(i\) ,活动 \(j\),始终让 \(j\) 保持在 \(i\) 的一半以前,这样复杂度就为 \(O(n)\)。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 1e7 + 5, mod = 1e9 + 7;
int n, len, Next[N], j, num[N];
string s; ll ans;
inline void getnext(){
Next[0] = Next[1] = 0; j = 0; ans = 1;
for(int i=1; i<len; ++i, j=Next[i]){
num[i] = num[j] + 1;
while(j && s[i] != s[j]) j = Next[j];
Next[i+1] = j + (s[i] == s[j]);
}
num[0] = 0; j = 0;
for(int i=1; i<len; ++i){
while(j && s[i] != s[j]) j = Next[j];
if(s[i] == s[j]) ++j;
while((j<<1) > i+1) j = Next[j];
ans = (__int128)ans * (num[j] + 1) % mod;
}
}
int main(){
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin>>n;
while(n--){
cin>>s; len = s.size();
ans = 1; getnext();
cout<<ans<<'\n';
} return 0;
}
[USACO15FEB] Censoring S
算是个kmp板子吧。在板子的基础上,用栈来模拟删除后的字符串,如果可以删除,那就退栈。再建立一个数组存还没匹配完的 \(j\) 的值。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
string s, t;
int ls, lt, Next[N], last[N], p[N];
int main(){
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin>>s>>t; ls = s.size(), lt = t.size();
for(int i=1, j=0; i<lt; ++i, j=Next[i]){
while(j && t[i] != t[j]) j = Next[j];
Next[i+1] = j + (t[i] == t[j]);
}
for(int i=0, j=0; i<ls; ++i){
while(j && s[i] != t[j]) j = Next[j];
if(s[i] == t[j]) ++j;
last[i] = j;
p[++p[0]] = i;
if(j == lt){
p[0] -= lt;
j = last[p[p[0]]];
}
}
for(int i=1; i<=p[0]; ++i) cout<<s[p[i]];
return 0;
}
[POI2006] OKR-Periods of Words
读完题目后可以发现,其实求的就是字符串 \(S\) 的前缀的最短公共前后缀。所以只需要在求Next数组时添加3行代码即可求出。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
int k, Next[N], j, p;
long long ans;
string s;
int main(){
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin>>k>>s;
for(int i=1; i<k; ++i, j=Next[i]){
while(j && s[i] != s[j]) j = Next[j];
Next[i+1] = j += (s[i] == s[j]);
p = j;
while(Next[p]) p = Next[p];
if(p) ans += i + 1 - p;
}
return cout<<ans, 0;
}
TLE73。不难发现,当字符串长的时候,会产生许多无用回溯。那么只需要记录下每一个回溯的值,在新的回溯时使用已有的结果,这样就能避免重复回溯。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
int k, Next[N], j, p, Last[N];
long long ans;
string s;
int main(){
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin>>k>>s;
for(int i=1; i<k; ++i, j=Next[i]){
while(j && s[i] != s[j]) j = Next[j];
Next[i+1] = j += (s[i] == s[j]);
if(Next[j]) Last[j] = Last[Next[j]];
else Last[j] = j;
if(Last[j]) ans += i + 1 - Last[j];
}
return cout<<ans, 0;
}
Trie 树
「POJ 3630」Phone List
Trie树板子。对于静态trie树,数组开多大其实要看运气(能开多大开多大),严格来说tire树空间应该开到 \(26^{26^{26…}}\) 一共有最长字符串长度个26,太大了。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 1;
int T, n, cnt;
bool opt;
struct node{
bool repeat, end;
int s[10], num;
}t[N];
string s;
inline void insert(string s){
int len = s.size(), now = 0;
for(int i=0; i<len; ++i){
int ch = s[i] - '0';
if(!t[now].s[ch]) t[now].s[ch] = ++cnt, ++t[now].num;
now = t[now].s[ch];
if(t[now].end) opt = 1;
if(i == len-1){
if(t[now].num) opt = 1;
t[now].end = 1;
}
}
}
int main(){
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin>>T;
while(T--){
cin>>n;
memset(t, 0, sizeof t);
opt = 0, cnt = 0;
for(int i=1; i<=n; ++i) cin>>s, insert(s);
if(opt) cout<<"NO\n";
else cout<<"YES\n";
}
}
The XOR Largest Pair
首先,两个数的异或值最大不超过二进制位数最长的那个数的二进制位数,其次需要让其中一个数的取反与另一个数相似。这样就可以保证异或和最大。根据贪心思想,需要从最高位开始搜索,所以在存入字典树时也要从最高位开始存。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 1;
int n, mx, cnt, tot, ans, k;
bitset<32> num[N], nump[N];
struct node{ int s[2]; }t[N<<4];
inline void insert(int k){
int now = 0;
for(int i=30; i>=0; --i){
int Bit = num[k][i];
if(!t[now].s[Bit]) t[now].s[Bit] = ++cnt;
now = t[now].s[Bit];
}
}
inline int search(int k, int p){
int now = 0;
for(int i=30; i>=0; --i){
int Bit = !(num[k][i]);
if(t[now].s[Bit]){
now = t[now].s[Bit];
nump[p][i] = 1;
}
else{
if(t[now].s[!Bit]){
now = t[now].s[!Bit];
nump[p][i] = 0;
}else break;
}
} return (int)nump[p].to_ulong();
}
int main(){
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin>>n;
for(int i=1; i<=n; ++i){
cin>>k, num[i] = k;
int len = num[i].size();
mx = max(mx, len);
insert(i);
}
for(int i=1; i<=n; ++i){
if(num[i].size() == mx){
nump[++tot] = num[i];
ans = max(ans, search(i, tot));
}
} return cout<<ans, 0;
}
The XOR-longest Path
这道题非常的巧妙。先求出dis[N]
的所有值,那么可以知道从 \(1\) 到 \(x\) 的路径为 \(dis(1,x)=dis(1,lca)\oplus dis(lca+1,x)\),那么 \(dis(1,x)\oplus dis(1,y)=dis(1,lca)\oplus dis(1,lca)\oplus dis(lca+1,x)\oplus dis(lca+1,y)=dis(x,y)\)。由此,这道题就和上道题一样了。
#include<bits/stdc++.h>
using namespace std;
#define Bit dis[k][i]
const int N = 1e5 + 1;
int n, h[N], cnt, t[N<<4][2], tot, Xor;
bitset<N> vis;
bitset<31> dis[N], ans;
struct edge{ int v, nt; bitset<31> w; }e[N];
inline void add(int u, int v, int w){
e[++cnt].v = v, e[cnt].nt = h[u], e[cnt].w = w; h[u] = cnt;
}
inline void insert(int k){
for(int i=30, now=0; i>=0; --i){
if(!t[now][Bit]) t[now][Bit] = ++tot;
now = t[now][Bit];
}
}
inline void search(int k){
ans = dis[k];
for(int i=30, now=0; i>=0; --i){
if(t[now][!Bit]) ans[i] = 1, now = t[now][!Bit];
else if(t[now][Bit]) ans[i] = 0, now = t[now][Bit];
else break;
}
Xor = max(Xor, (int)ans.to_ulong());
}
inline void dfs(int k){
vis[k] = 1;
insert(k);
search(k);
for(int i=h[k]; i; i=e[i].nt){
int v = e[i].v;
if(vis[v]) continue;
dis[v] = dis[k] ^ e[i].w;
dfs(v);
}
}
int main(){
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin>>n;
for(int i=1, a, b, v; i<n; ++i) cin>>a>>b>>v, add(a, b, v);
dfs(1); return cout<<Xor, 0;
}
[学习笔记] hash & kmp & Trie树 - 字符串的更多相关文章
- SQL反模式学习笔记3 单纯的树
2014-10-11 在树形结构中,实例被称为节点.每个节点都有多个子节点与一个父节点. 最上层的节点叫做根(root)节点,它没有父节点. 最底层的没有子节点的节点叫做叶(leaf). 中间的节点简 ...
- golang学习笔记14 golang substring 截取字符串
golang学习笔记14 golang substring 截取字符串golang 没有java那样的substring函数,但支持直接根据 index 截取字符串mystr := "hel ...
- AC自动机学习笔记-2(Trie图&&last优化)
我是连月更都做不到的蒟蒻博主QwQ 考虑到我太菜了,考完noip就要退役了,所以我决定还是把博客的倒数第二篇博客给写了,也算是填了一个坑吧.(最后一篇?当然是悲怆のnoip退役记啦QAQ) 所以我们今 ...
- POJ3376 Finding Palindromes —— 扩展KMP + Trie树
题目链接:https://vjudge.net/problem/POJ-3376 Finding Palindromes Time Limit: 10000MS Memory Limit: 262 ...
- Swift 2.0 字符串学习笔记(建议掌握OC字符串知识的翻阅)
自己公司开现在使用OC语言在写,但Swift似乎是苹果更推荐使用的开发语言,估计也是未来开发的趋势,自己以前有接触swift,但又由于公司的项目赶,也没有时间去好好地学习这款开发语言.现在年底了,项目 ...
- Python学习笔记(二):字符串类型
在上一篇随笔(https://www.cnblogs.com/g-qiang/p/10448813.html)中,说到 Python 有六种标准数据类型,而数字类型和字符串类型又是其中基本的数据类型. ...
- [Python学习笔记][第四章Python字符串]
2016/1/28学习内容 第四章 Python字符串与正则表达式之字符串 编码规则 UTF-8 以1个字节表示英语字符(兼容ASCII),以3个字节表示中文及其他语言,UTF-8对全世界所有国家需要 ...
- Mysql高级操作学习笔记:索引结构、树的区别、索引优缺点、创建索引原则(我们对哪种数据创建索引)、索引分类、Sql性能分析、索引使用、索引失效、索引设计原则
Mysql高级操作 索引概述: 索引是高效获取数据的数据结构 索引结构: B+Tree() Hash(不支持范围查询,精准匹配效率极高) 树的区别: 二叉树:可能产生不平衡,顺序数据可能会出现链表结构 ...
- knockoutJS学习笔记01:从拼接字符串到编写模板引擎
开篇 关于knockout的文章,园里已经有很多大神写过了,而且都写得很好.其实knockout学习起来还是很容易的,看看官网的demo和园里的文章,练习练习就可以上手了(仅限使用,不包含研究源码). ...
- Swift学习笔记(4):字符串
目录: 初始化 常用方法或属性 字符串索引 初始化 创建一个空字符串作为初始值: var emptyString = "" // 空字符串字面量 var anotherEmptyS ...
随机推荐
- 58同城的登录(RSA算法)
Tips:当你看到这个提示的时候,说明当前的文章是由原emlog博客系统搬迁至此的,文章发布时间已过于久远,编排和内容不一定完整,还请谅解` 58同城的登录(RSA算法) 日期:2016-11-23 ...
- 有点儿神奇,原来vue3的setup语法糖中组件无需注册因为这个
前言 众所周知,在vue2的时候使用一个vue组件要么全局注册,要么局部注册.但是在setup语法糖中直接将组件import导入无需注册就可以使用,你知道这是为什么呢?注:本文中使用的vue版本为3. ...
- Service Mesh技术详解
深入探讨Service Mesh的基本概念和核心技术,涵盖了服务发现.负载均衡.断路器与熔断机制,以及数据平面与控制平面的详细工作原理和实现方法. 关注作者,复旦博士,分享云服务领域全维度开发技术.拥 ...
- OpenBMB × Hugging Face × THUNLP,联袂献上经典大模型课
这个夏天,THUNLP 携手 Hugging Face 和 OpenBMB,推出 大模型公开课第二季.在大模型公开课第二季中,将有全球知名开源社区 OpenBMB X Hugging Face 梦幻联 ...
- python3 安装pyodbc失败 pip3 install pyodbc
python3 安装pyodbc失败 报错1: 关键报错信息: fatal error: sql.h: No such file or directory [root@centfos python3 ...
- 韦东山IMX6ULL Linux开发板基于Buildroot系统QT应用环境配置开发运行
@ 目录 一. 编译系统 1.设置交叉编译工具链 2.编译系统 二. QT下载 1.安装 Qtcreator 2.创建第一个程序 3.配置 QtCreator 开发环境 4.移植QT程序到开发板 一. ...
- ffmpeg -使用总结
ffmpeg 使用总结,不定期更新 ---------------------------------------- 1. 将截图合成影片: ffmpeg -i ./shot/%d.tiff -thr ...
- Java常见的加密方式
前言 传说在古罗马时代,发生了一次大战.正当敌方部队向罗马城推进时,古罗马皇帝凯撒向前线司令官发出了一封密信:VWRS WUDIILF.这封密信被敌方情报人员翻遍英文字典,也查不出这两个词的意思. 此 ...
- AI生成前端组件的价值思考
想法来源 这个想法来源于我自己的需求,我自己首先就是最精准的目标用户,在这个AI时代,我希望AI可以帮我尽量多地干活. 结合自己的日常独立开发情况,发现花在调前端组件样式上的时间很多,因此思考能不能让 ...
- oeasy教您玩转linux010206toilet
我们来回顾一下 上一部分我们都讲了什么? 用apt查询并下载了figlet 玩了一下字符画 设置了字符画的字体 但是没有修改颜色 这次我们来找找另一个命令toilet apt search toile ...