YuuFrag学习记录 共享笔记库
与你的相遇就是奇迹

给定一个字符串 s,你可以通过在字符串前面添加字符将其转换为回文串。找到并返回可以用这种方式转换的最短回文串。
示例 1: 输入: s = "aacecaaa" 输出: "aaacecaaa"
示例 2: 输入: s = "abcd" 输出: "dcbabcd"
提示:
0 <= s.length <= 5 * 104s仅由小写英文字母组成
看到回文串第一反应是马拉车或者dp。
但是认真思考样例 ——
在示例一中,我们添加的前缀是"a",恰好是"aacecaa"这个最长回文前缀去掉之后的部分再进行一个反转。 示例二同理
仔细一想确乎是这样 ——
所以把原问题转化成“找 s 的最长回文前缀”
那么这又想到马拉车了 —— 跑马拉车的时候维护一下可以触碰到最左侧的回文串的长度,找到最长的即可
于是可以有第一种解法。
但是又看到了找”前缀“这件事情,所以不妨看看KMP能不能解 ——
先明确KMP维护的pi[i]表示P[0...i]中最长的相同的前后缀,所以就要寻找最长回文前缀的问题化归成最长相同前后缀问题 ——
“把回文串沿着中心劈开,把前一半反转一下就和后一半一致”
想到构造 ——
combine = s + "#" + reverse(s)
直接看例子
a a c e c a a a # a a a c e c a a
^
把一些可以并行执行的 CPU 工作交给 Worker 去做,比如资产加载、可见性计算、后台统计等。
核心思想 ——
业务模块决定要做什么
JobSystem 只决定什么时候做、在哪个线程做、做完以后如何通知
也就是说,AssetManager 负责加载什么资产,Renderer 负责哪些渲染数据可以并行处理,而 JobSystem 本身不理解 Asset,也不理解 Renderer。
它只是一个调度器。
ChikaProfiler
↑
ChikaJobs
↑
├───────────────┐
│ │
ChikaAsset ChikaRender
↑ ↑
└───────┬───────┘
│
EngineContext
ChikaJobs 只依赖 ChikaProfiler,不依赖 Asset 和 Render。
这样设计是为了让 JobSystem 保持干净:
假设现在 AssetManager 想异步加载一个 Shader。
最简单的做法可能是直接开一个线程:
std::thread([path]
{
LoadShader(path);
}).detach();
这看起来很方便,但问题非常多:
所以引入 JobSystem。
上层不直接创建线程,而是提交一个任务:
JobHandle handle = jobs.Schedule("Asset.LoadShader", []
{
LoadShader();
});
JobSystem 内部负责:
这样业务层只关心“我要做什么”,不关心“线程怎么调度”。
外部模块 / 主线程
│
▼
Schedule Job
│
▼
JobStorage 分配 Slot
│
▼
放入可执行队列
│
▼
Worker 取任务
│
▼
执行 callable
│
▼
Completed / Failed / Cancelled
│
▼
Wait / Release / Detach
简单来说 ——
JobSystem 可以粗略分为五块:
|部分|作用| |