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

字符串的最小表示法,就是对于一个字符串,能够将它的最后一位放到第一位来,依次类推,一共有n种变形,n为字符串长度算法

例如:ide

s="00ab"spa

变形有(省略引号)b00a ab00 0ab0指针

一共4种code

那么找到其中字典序最小的一个,用的算法即是这个。blog

定义三个指针,i,j,k字符串

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

 

首先,若是s[i]<s[j]那么很明显j++event

若是s[i]>s[j]那么也很明显i=j++class

省下的就是若是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
相关文章
相关标签/搜索