Minimum Index
题意
求字符串所有前缀的所有后缀表示中字典序最小的位置集合,最终转换为1112进制表示。比如aab,有三个前缀分别为a,aa,aab。其中a的后缀只有一个a,位置下标1;aa有两个后缀,字典序最小的是a,下标为2;aab有三个后缀,字典序最小的是aab,下标是1。答案为 (1*(1112)^2+2*(1112)^1+1*(1112)^0)
字符串长度1e6
分析
在求字符串的最小表示法中,有一个叫做Lyndon分解的求法,Lyndon分解可以使用Duval算法。详情可以参考 oi-wiki。
设(d[j]) 为前缀 j 的字典序最小后缀的起始位置,i, j, k 指针与oi-wiki中介绍的一致。对于下面三种情况讨论d[j]的求解
(j - k) 为 近似Lyndon串前缀的循环节长度。
- (s[j] == s[k]), 那么d[j] = d[k] + (j - k); 本质上是取了 j 所在循环节的开头位置。((s=wwwoverline{w}) 中 (overline{w}) 的开头)
- (s[j] > s[k]),那么 d[j] = i; 当前(s[i..j]) 是一个Lyndon串,所以d[j] = i;
- (s[j] < s[k]),Duval算法中会重新处理 j 所在的这一段((s=wwwoverline{w}) 中 (overline{w})), i会被置为这一段的开头,继续后面的分解过程。这里有一个特殊情况需要考虑,如果 (j == k + 1),那么 j 就是下一次分解的开头, i 会被置为 j,所以要手动将d[j] = j。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
#define dbg(x...) do { cout << "