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