找一个字符串的最小字典排序,最小表示法返回最小字典排序首字母的下标。
最小表示法的复杂度为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; }