最小(大)表示法是字符串問題中不一樣於匹配與失配的另外一種O(n)的算法,它主要解決的是字符串的同構問題。將單個字符串循環左移右移算做該串的同構,最小(大)表示法可以在O(n)時間內求出這個串的全部同構串中的字典序最小的串的起始位置。因爲代碼簡潔容易理解,所以在處理同類問題時每每比後綴數組以及各類匹配算法更加方便運用。算法
代碼以下(注意下標是從0開始的,返回的下標也從0開始):數組
1 #include<stdio.h>
2 #include<string.h>
3 #include<algorithm>
4 using namespace std; 5
6 const int maxn=1e5+5; 7 char s[maxn<<1]; 8
9 inline int max(int a,int b){return a>b?a:b;} 10 inline int min(int a,int b){return a<b?a:b;} 11
12 int MINR(char s[],int l){ //s是原串(未加倍過),l是原串長
13 for(int i=0;i<l;++i)s[l+i]=s[i]; //將s串加倍
14 s[2*l]=0; 15 int i=0,j=1; //利用i,j指針移動
16 while(i<l&&j<l){ 17 int k=0; 18 while(s[i+k]==s[j+k]&&k<l)++k; //不斷比較直到比較完長度爲l的串或兩個子串不相等
19 if(k==l)return min(i,j); //若比較出長度爲l則直接返回靠前的那個串的開始位置
20 if(s[i+k]>s[j+k])i=max(i+k+1,j+1); //i串比j串大,那麼i到i+k中的串都比j串大,i能夠直接移動到i+k+1位置,而起始位置比j小的確定都在j移動過程當中比較過,因此i能夠直接移動到j+1位置,所以取這兩值的最大值
21 else j=max(j+k+1,i+1); //同上
22 } 23 return min(i,j); //返回位置靠前的下標
24 } 25
26 int MAXR(char s[],int l){ 27 for(int i=0;i<l;++i)s[l+i]=s[i]; 28 s[2*l]=0; 29 int i=0,j=1; 30 while(i<l&&j<l){ 31 int k=0; 32 while(s[i+k]==s[j+k]&&k<l)++k; 33 if(k==l)return min(i,j); 34 if(s[i+k]<s[j+k])i=max(i+k+1,j+1); 35 else j=max(j+k+1,i+1); 36 } 37 return min(i,j); 38 }