Fibonacci
思路
-
可以发现, 连续的三个字母不全相同, 所以 | s |
3 * |t| -
|S| 枚举一下即可(好像能证明但是不会),1e6 左右
-
所以只要暴力算出来一段 S, 然后枚举起点开始匹配即可
40 分
枚举即可
100 分
- 使用类似倍增的方法
- st[i][j] 表示从 t[i] 出发, 在 s[j] 中找子序列, 能匹配到 t[st[i][j]]
- 因为 s[j] = s[j-1] + s[j-2], 所以 st[i][j] = st[i][j-1] + st[i+st[i][j-1]][j-2]
- 然后考虑怎么枚举起点
- s[j] 可以拆成 s[j-1] + s[j-2]
- s[j-1] 可以继续拆, 直到 j = 1 或 0
- 每次删掉最头上的一个 j = 1 或 0 即可
- 然后用 st 对剩下的进行匹配
代码
40 分
- 考场代码
#include <bits/stdc++.h> #define int long long using namespace std; const int N = 1e5 + 10; string s1, s2, s; string t; signed main(){ // freopen("1.in", "r", stdin); cin >> t; s1 = "b"; s2 = "a"; for(int i = 2; i; i++){ s = s2 + s1; s1 = s2, s2 = s; if(s.size() > (int)6e4){ break; } } int mini = (int)1e18, cnt = 0; for(int i = 0; i < (int)s.size() - (int)t.size() + 1; i++){ int step = 0, k = 0; for(int j = i; j < (int)s.size(); j++){ step++; cnt++; if(s[j] == t[k]){ k++; } if(k == (int)t.size()){ break; } } if(k == (int)t.size()){ mini = min(mini, step); } } cout << mini << "\n"; }
100 分
#include <bits/stdc++.h> #define int long long using namespace std; const int INF = 1e18; const int N = 1.5e5 + 10; int n; int len, p, mini; int fibo[35], st[N][35]; char t[N]; vector <int> que; void Calc(int x){ if(p > n){ return; } if(x <= 1 || p + st[p][x] <= n){ // x <= 1 表示递归找到底了 p += st[p][x]; // 该匹配哪一位了 len += fibo[x]; // |s| return; } Calc(x - 1), Calc(x - 2); } void Solve(){ // 用 st 算挨个在 que 中找子序列的 |s| len = 0; // |s| p = 1; // 该去匹配 t 的第 p 位了(下标从 1 开始) for(int i = que.size() - 1; i >= 0; i--){ Calc(que[i]); } if(p > n){ mini = min(mini, len); } } signed main(){ // freopen("1.in", "r", stdin); cin >> (t + 1); n = strlen(t + 1); for(int i = 1; i <= n; i++){ // 初始化: 第一位和 s_0 / s_1 能匹配上 if(t[i] == 'a'){ st[i][1] = 1; }else{ st[i][0] = 1; } } int up = 31; mini = 3 * n; for(int i = n; i >= 1; i--){ for(int j = 2; j <= up; j++){ // 类似倍增的操作 st[i][j] = st[i][j - 1] + st[i + st[i][j - 1]][j - 2]; } } fibo[0] = fibo[1] = 1; for(int i = 2; i <= up; i++){ // 递推斐波那契序列, 用于计算 |s| fibo[i] = fibo[i - 1] + fibo[i - 2]; } que.push_back(up); while(!que.empty()){ Solve(); while(que.back() >= 2){ int ba = que.back(); que.pop_back(); que.push_back(ba - 2); que.push_back(ba - 1); } que.pop_back(); // 每次删掉一个最小单位(和 for(int i = 1; i <= n; i++) 没多大区别) } cout << mini << "\n"; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话