最小表示
字符串最小表示法 O(n)算法
2014-10-07 15:58?6869人閱讀?評論(5)?收藏?舉報版權聲明:本文為博主原創文章,未經博主允許不得轉載。
網上看了這篇文章后還是感覺有些地方講的沒有詳細的證明所以添加了一點 紅色字是博主寫的
求字符串的循環最小表示:
?
上面說的兩個字符串同構的,并沒有直接先求出Min(s),而是通過指針移動,當某次匹配串長時,那個位置就是Min(s)。而這里的問題就是:不是給定兩個串,而是給出一個串,求它的Min(s),eg:Min(“babba”) = 4。那么由于這里并非要求兩個串的同構,而是直接求它的最小表示,由于源串和目標串相同,所以處理起來既容易又需要有一些變化:我們仍然設置兩個指針,i, j,其中i指向0,j指向1,仍然采用上面的滑動方式:
?
(1)? 利用兩個指針i, j。初始化時i指向0, j指向1。
?
(2)? k = 0開始,檢驗s[i+k] 與 s[j+k] 對應的字符是否相等,如果相等則k++,一直下去,直到找到第一個不同,(若k試了一個字符串的長度也沒找到不同,則那個位置就是最小表示位置,算法終止并返回)。則該過程中,s[i+k] 與 s[j+k]的大小關系,有三種情況:
? 證明的時候假設(i<j)的,無傷大雅 ;
???? (A). s[i+k] > s[j+k],則i滑動到i+k+1處 --- 即s1[i->i+k]不會是該循環字符串的“最小表示”的前綴。
?證明如下
? ??
???? (B). s[i+k] < s[j+k],則j滑動到j+k+1處,原因同上。
?證明如下
???? (C). s[i+k] = s[j+k],則 k++; if (k == len) 返回結果。?
??? 注:這里滑動方式有個小細節,若滑動后i == j,將正在變化的那個指針再+1。直到p1、p2把整個字符串都檢驗完畢,返回兩者中小于 len 的值。
?
(3)?? 如果 k == len, 則返回i與j中的最小值
?
????? 如果 i >= len?? 則返回j
?
????? 如果 j >= len?? 則返回i
如果看了上一篇文章 很容易對這里的i,j 產生誤會 ?誤以為i為ans,j為比較指針
實際上這題中 i,j 都可能存有ans 兩者互相更新,直到有一個更新后超過了len(包括len) 的時候 另一個即為正解
(4)?? 進一步的優化,例如:i要移到i+k+1時,如果i+k+1 <= p2的話,可以直接把i移到 j+1,因為,j到j+k已經檢驗過了該前綴比以i到i+k之間任何一個位前綴都小;j時的類似,移動到i+1。
?這個優化就無需解釋了
至此,求一個字符串的循環最小表示在O(n)時間實現,感謝大牛的論文。其中實現時的小細節“如果滑動后p1 == p2,將正在變化的那個指針再+1”,開始沒有考慮,害得我想了幾個小時都覺得無法進行正確的移動。具體例題有兩個:http://acm.zju.edu.cn 的2006和1729題。一個是10000規模一個是100000規模。運行時間前者是0S,后者是0.05S。
- int?MinimumRepresentation(int?*s,?int?l)????
- {????
- ? ?int i,j,k;
? ? i=0;j=1;k=0;
? ? while(i<l&&j<l&&k<l)
? ? {
? ? ? ? int t=s[(i+k)%l]-s[(j+k)%l];
? ? ? ? if(!t)
? ? ? ? ? ? k++;
? ? ? ? else
? ? ? ? {
? ? ? ? ? ? if(t>0)
? ? ? ? ? ? i=i+k+1;
? ? ? ? ? ? else
? ? ? ? ? ? j=j+k+1;
? ? ? ? ? ? if(i==j)
? ? ? ? ? ? ? ? j++;
? ? ? ? ? ? k=0;
? ? ? ? }
? ? }
? ? return i>j?j:i; - }???
總結
- 上一篇: 现在最便宜的小轿车多少钱啊?
- 下一篇: twofive(记忆搜索)