最小表示法

找一个字符串的最小字典排序,最小表示法返回最小字典排序首字母的下标。

最小表示法的复杂度为O(n)。

实现方法:

(1).利用两个指针p1,p2。初始化时p1指向s[0],p2指向s[1]。

(2).k=0开始,检验s[p1+k]和s[p2+k]是否相等,相等则k++,一直下去,直到找到第一个不相同的字符(若k试了一个字符串的长度也没找到不同,则那个位置就是最小表示位置,算法终止并返回)。该过程中s[p1+k]和s[p2+k]的关系有三种:

  1).s[p1+k]>s[p2+k],p1滑动到p1+k+1处,s[p1--p1+k-1]不会是循环字符串的"最小表示"的前缀。

  2).s[p1+k]<s[p2+k],p2滑动到p2+k+1处。

  3).s[p1+k]==s[p2+k],则k++,if(k==len)返回结果。

  若滑动后p1==p2,将正在变化的那个指针在+1.直到p1,p2把整个字符串都检验完毕,返回两者中小于len的值。

(3).如果 k==len,则返回min( i , j )

  如果 p1>=len,返回 p2

  如果 p2>=len,返回p1

进一步的优化,例如:p1要移到p1+k+1时,如果p1+k+1 <= p2的话,可以直接把p1移到 p2,而p2加1,因为我们已经证明了p2之前的所有位置都不能是最小表示的起点;p2时的类似,移动到p1+1。

int getmin()
{
    int len=strlen(str);
    int i=0,j=1,k=0;
    while(i<len && j<len && k<len)
    {
        int t=str[(i+k)%len]-str[(j+k)%len];
        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;
}

 

posted @ 2013-08-03 23:18  yongren1zu  阅读(218)  评论(0编辑  收藏  举报