「学习笔记」字符串最小表示法 (简)
「学习笔记」字符串最小表示法 (简)
过程
维护三个指针 \(i,j,k\).
\(i,j\) 表示目前正在进行比较的两个起始位置, 保证 \(i<j\), \(k\) 表示这两个起始位置对应的串的 \(LCP\) 长度.
每次对 \(k++\) , 然后根据 \(s[i+k]\) 和 \(s[j+k]\) 的大小关系调整 \(i,j\) 的位置.
若 \(s[i+k]<s[j+k]\), 那么在区间 \([j,j+k]\) 范围内的起始位置 \(x\) 肯定不是最优解, 因为 \(i+x-j\) 一定比它优, 所以让 \(j=j+k+1,k=0\).
若 \(s[i+k] > s[j+k]\), 按照上面的操作, 在区间 \((i,j)\) 范围内的其实位置已经被排除了, 所以直接让 \(i=j,j++,k=0\).
若 \(s[i+k] = s[j+k]\), 则判断 \(k\) 是否等于 \(n\), 若等于 \(n\) 则输出 \(i\).
算法过程中若 \(j>n\), 则同样输出 \(i\).
代码
void Run(){ // 字符串从 0 开始
int i=0,j=1,k=0;
while(i<n&&j<n&&k<n){
if(a[(i+k)%n]>a[(j+k)%n]){
i=i+k+1,k=0;
if(i<j) i=j,j++;
else swap(i,j);
}
else if(a[(i+k)%n]<a[(j+k)%n]) j=j+k+1,k=0;
else k++;
if(i==j) j++;
}
}