有人可以向我解释一下,按字典顺序排列的最小字符串是什么意思。这是来自堆栈交换的示例
考虑一个长度为n(1 <= n <= 100000)的字符串。确定其 最小词典旋转。例如, 字符串“ alabala”是:
阿拉巴拉
labalaa
阿巴拉尔
巴拉拉
alaalab
laalaba
aalabal
其中最小的是“ aalabal”。
所以这说最小的是“ aalabal”,是因为“ aa”在开始时出现两次吗?我无法解释什么使“ aalabal”最小?有人可以提供一些见识吗?
答案 0 :(得分:0)
由于问题“是什么使“ aalabal”最小?”,答案不可避免:“ lexicographical order”。
答案 1 :(得分:0)
UPD :抱歉,我只是重新阅读了您的问题,看来您被困在词典编纂部分。无论如何,请遵循其他用户提供的一些链接,然后稍后进行检查。
有一种使用Suffix Array(SA)解决此问题的方法。让您的字符串为S
,然后将S
与自身连接起来,然后应用SA。 SA的输出是一个数组,每个后缀的位置均按字母顺序排序。您可以迭代并查找从[0, |S|)
范围内的任何位置开始的第一个后缀。您需要考虑一下为什么会起作用,但是最后您可以很容易地弄清楚。
例如,让S = alabala
。您可以在下图中看到alabalaalabala
的SA输出:
位置在[0, |S|) = [0, 7)
范围内的第一个后缀是SA[i] = 6
,对应于后缀aalabala
。
有时在应用SA(实现详细信息)之前在字符串的末尾添加特殊字符很方便。
您可以检查以下在O(Nlg ^ 2N)中运行的SA的简短实现,实现速度更快,但是我想这个SA背后的想法是最简单的。
g++ sa.cpp
)N = 15, S = alabalaalabala$
。源代码
#include <iostream>
#include <algorithm>
using namespace std;
const int
MaxN = 200005;
int N;
int i, k;
char s[MaxN];
int ord[MaxN];
int pos[MaxN];
int buc[MaxN];
bool cmp(const int& a, const int& b) {
if (pos[a] != pos[b])
return pos[a] < pos[b];
if (a + k < N && b + k < N)
return pos[a + k] < pos[b + k];
return a > b;
}
int main() {
cin >> N;
cin >> s;
for (i = 0; i < N; i++) {
ord[i] = i;
pos[i] = s[i];
}
for (k = 0; k < N; k = k ? 2 * k : 1) {
sort(ord, ord + N, cmp);
for (i = 1; i < N; i++)
buc[i] = buc[i-1] + cmp(ord[i-1], ord[i]);
for (i = 0; i < N; i++)
pos[ord[i]] = buc[i];
}
for (i = 0; i < N; i++)
cout << ord[i] << " - " << (s + ord[i]) << endl;
return 0;
}