【算法】字符串的最小表示法


字符串的最小表示法,就是對於一個字符串,可以將它的最后一位放到第一位來,依次類推,一共有n種變形,n為字符串長度

例如:

s="00ab"

變形有(省略引號)b00a ab00 0ab0

一共4種

那么找到其中字典序最小的一個,用的算法便是這個。

定義三個指針,i,j,k

初始i=0;j=1;k=0

 

首先,如果s[i]<s[j]那么很明顯j++

如果s[i]>s[j]那么也很明顯i=j++

省下的就是如果s[i]==s[j]的時候。

這時候有一個性質就是在i和j之間的所有的字符一定是大於等於s[i]的

另k=0,循環尋找第一個s[i+k]!=s[j+k]的位置

如果s[i+k]<s[j+k]那么j+=k+1

為什么呢?

首先s[i]到s[i+k-1]一定是大於等於s[i],因為如果其中有一個數小於s[i],那么這個數一定在s[j]到s[j+k-1]中存在,又因為必定有一個會在后面,所以如果s[j]先碰到了,那么一定不會繼續到k的位置的,所以一定不存在比s[i]小的字符。

所以從其中的任意一個字符開始當作起始點,都不會比現在更小,所以只有從選出來的序列的后面那一個字符開始才有可能會是最小。

所以j+=k+1

如果序列中某個數和s[i]相等的話,那么一定會有之前或者以后再這個位置起始過,所以不需要再從這個位置進行起始。

因為在這里i和j是等價的,i在前和j在前的結果是一樣的,所以i和j的處理是相同的,下面就不仔細的進行講解了,直接貼代碼:

 

還有就是如果i==j那么讓j++就可以回到原先的狀態了

最后的時候,肯定是小的不會動,而大的會不停的向后移動,所以最后只需要輸出i和j最小的一個即可

int getmin(char *s){
    int n=strlen(s);
    int i=0,j=1,k=0,t;
    while(i<n && j<n && k<n){
        t=s[(i+k)%n]-s[(j+k)%n];
        if (!t) k++;
        else{
            if (t>0) i+=k+1; 
            else j+=k+1;
            if (i==j) j++;
            k=0;
        }
    }
    return i<j?i:j;
}
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM