Loading docs/string/minimal-string.md +10 −9 Original line number Diff line number Diff line Loading @@ -18,27 +18,28 @@ $$ ## simple 的暴力 我们直接比较与 $S$ 同构的所有字符串,共 $n$ 个。 每次保留当前字典序最小的字符串与剩余的字符串比较。 我们每次比较 $i$ 和 $j$ 开始的循环同构,把当前比较到的位置记作 $k$ ,每次遇到不一样的字符时便把大的跳过,最后剩下的就是最优解。 ```cpp int k = 0, i = 0, j = 1; for (; j < n; j++) { while (k < n && i < n && j < n) { if (sec[(i + k) % n] == sec[(j + k) % n]) { k++; ++k; } else { if (sec[(i + k) % n] > sec[(j + k) % n] % n) { i = j; } if (sec[(i + k) % n] > sec[(j + k) % n]) ++i; else ++j; k = 0; if (i == j) i++; } } i = min(i, j); ``` 随机数据下表现良好,但是可以构造特殊数据卡掉。 例如:对于 $aaa\cdots aaa$ , 不难发现这个算法的复杂度退化为 $O(n^2)$ 例如:对于 $aaa\cdots aab$ , 不难发现这个算法的复杂度退化为 $O(n^2)$ 。 我们发现,当字符串中出现多个连续重复子串时,此算法效率降低,我们考虑优化这个过程。 Loading Loading
docs/string/minimal-string.md +10 −9 Original line number Diff line number Diff line Loading @@ -18,27 +18,28 @@ $$ ## simple 的暴力 我们直接比较与 $S$ 同构的所有字符串,共 $n$ 个。 每次保留当前字典序最小的字符串与剩余的字符串比较。 我们每次比较 $i$ 和 $j$ 开始的循环同构,把当前比较到的位置记作 $k$ ,每次遇到不一样的字符时便把大的跳过,最后剩下的就是最优解。 ```cpp int k = 0, i = 0, j = 1; for (; j < n; j++) { while (k < n && i < n && j < n) { if (sec[(i + k) % n] == sec[(j + k) % n]) { k++; ++k; } else { if (sec[(i + k) % n] > sec[(j + k) % n] % n) { i = j; } if (sec[(i + k) % n] > sec[(j + k) % n]) ++i; else ++j; k = 0; if (i == j) i++; } } i = min(i, j); ``` 随机数据下表现良好,但是可以构造特殊数据卡掉。 例如:对于 $aaa\cdots aaa$ , 不难发现这个算法的复杂度退化为 $O(n^2)$ 例如:对于 $aaa\cdots aab$ , 不难发现这个算法的复杂度退化为 $O(n^2)$ 。 我们发现,当字符串中出现多个连续重复子串时,此算法效率降低,我们考虑优化这个过程。 Loading