字符串的最大最小表示法

算法描述:給定一個字符串s,可以進行左循環(右循環)移位,總共的結果有strlen(s)種,在這些結果中最小的是那個,最大的是哪個。
詳解描述
論文傳送門
HDU3374
題目意思:給定一個字符串s求循環幾次會是字典序最小的(最小表示),最大的(最大表示),分別會出現幾次。
思路:第一個用上面提到算法就可以算,後面的只需要求出以爲後的有幾個循環就就好了。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1e6+10;
int Next[maxn];
int get_min(char s[])//最小表示法
{
    int len=strlen(s);
    int i=0,j=1,k=0;
    while(i<len&&j<len)
    {
        k=0;
        while(s[(i+k)%len]==s[(j+k)%len]&&k<len)
            k++;
            if(k>=len) break;
        if(s[(i+k)%len]>s[(j+k)%len])
        {
            i=i+k+1;
            if(i==j)
                i++;
        }
        else
        {
            j=j+k+1;
            if(j==i)
                j++;
        }
    }
    return min(i,j);
}
int get_max(char s[])//最大表示法
{
    int len=strlen(s);
    int i=0,j=1,k=0;
    while(i<len&&j<len)
    {
        k=0;
        while(s[(i+k)%len]==s[(j+k)%len]&&k<len)
            k++;
            if(k>=len) break;
        if(s[(i+k)%len]<s[(j+k)%len])
        {
            i=i+k+1;
            if(i==j)
                j++;
        }
        else
        {
            j=j+k+1;
            if(j==i)
                i++;
        }
    }
    return min(i,j);
}
void get_next(char s[])
{
    int len=strlen(s);
    int i=0,j=-1;
    Next[0]=-1;
    while(i<len)
    {
        if(j==-1||s[i]==s[j])
        {
            i++,j++;
            Next[i]=j;
        }
        else
            j=Next[j];
    }
}
char s[maxn],tmp1[maxn],tmp2[maxn];
int main()
{
    while(~scanf("%s",&s))
    {
        int len=strlen(s);
        int Min=get_min(s),Max=get_max(s),cont=0;
        for(int i=Min; i<len; i++)
            tmp1[cont++]=s[i];
        for(int i=0; i<Min; i++)
            tmp1[cont++]=s[i];
        cont=0;
        for(int i=Max; i<len; i++)
            tmp2[cont++]=s[i];
        for(int i=0; i<Max; i++)
            tmp2[cont++]=s[i];
            get_next(tmp1);
            printf("%d %d ",Min+1,len%(len-Next[len])==0?len/(len-Next[len]):1);
            get_next(tmp2);
            printf("%d %d\n",Max+1,len%(len-Next[len])==0?len/(len-Next[len]):1);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章