最小表示法总结

问题解决

一般用于解决一类最小表示或最小串的问题。

问题引入

例题:poj1509

求它的循环串中字典序最小的串的开头。

问题解决

暴力

找到所有的串存下来然后排序,复杂度\(\Theta(n^2)\)的。

诡异做法

建个后缀自动机然后遍历最小的字母边即可。

正经一点的

考虑两个指针\(i\),\(j\),一边扫过去的时候暴力求一下\(i,j\)\(lcp\)的长度,然后比一下\(lcp\)后一位,把大的那个指针往后移那么多位即可。

代码实现

/*
  mail: [email protected]
  author: MLEAutoMaton
  This Code is made by MLEAutoMaton
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<iostream>
using namespace std;
#define ll long long
#define REP(a,b,c) for(int a=b;a<=c;a++)
#define re register
#define file(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
inline int gi(){
    int f=1,sum=0;char ch=getchar();
    while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
    return f*sum;
}
const int N=100010;
char s[N];int n;
int main(){
    int T=gi();
    while(T--){
        scanf("%s",s);n=strlen(s);
        int i=0,j=1;
        while(i<n && j<n){
            int k=0;
            while(k<=n && s[(i+k)%n]==s[(j+k)%n])k++;
            if(k>n)break;
            if(s[(i+k)%n]<=s[(j+k)%n])j=j+k+1;
            else i=i+k+1;
            if(i==j)j=i+1;
        }
        printf("%d\n",min(i+1,j+1));
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/fexuile/p/11625861.html
今日推荐