字符串循环同构的最小表示法(转)
循環字符串的最小表示法的問題可以這樣描述:
對于一個字符串S,求S的循環的同構字符串S’中字典序最小的一個。
由于語言能力有限,還是用實際例子來解釋比較容易:
設S=bcad,且S’是S的循環同構的串。S’可以是bcad或者cadb,adbc,dbca。而且最小表示的S’是adbc。
對于字符串循環同構的最小表示法,其問題實質是求S串的一個位置,從這個位置開始循環輸出S,得到的S’字典序最小。
一種樸素的方法是設計i,j兩個指針。其中i指向最小表示的位置,j作為比較指針。
令i=0,j=1
如果S[i] > S[j] i=j, j=i+1
如果S[i] < S[j] j++
如果S[i]==S[j]?設指針k,分別從i和j位置向下比較,直到S[i] != S[j]
?????????如果S[i+k] > S[j+k] i=j,j=i+1
?????????否則j++
返回i
起初,我想在j指針后移的過程中加入一個優化。就是j每次不是加1,而是移動到l位置。其中,l>j且S[l]<=S[j]。但是,即使加入這一優化,在遇到bbb…bbbbbba這樣的字符串時復雜度將退化到O(n^2)。
注意到,樸素算法的缺陷在于斜體的情況下i指針的移動太少了。針對這一問題改進就得到了最小表示法的算法。最小表示法的算法思路是維護兩個指針i,j。
令i=0,j=1
如果S[i] > S[j] i=j, j=i+1
如果S[i] < S[j] j++
如果S[i]==S[j]?設指針k,分別從i和j位置向下比較,直到S[i] != S[j]
?????????如果S[i+k] > S[j+k] i=i+k
?????????否則j++
返回i和j的小者
注意到上面兩個算法唯一的區別是粗體的一行。這一行就把復雜度降到O(n)了。
值得一提的是,與KMP類似,最小表示法處理的是一個字符串S的性質,而不是看論文時給人感覺的處理兩個字符串。
應用最小表示法判斷兩個字符串同構,只要將兩個串的最小表示求出來,然后從最小表示開始比較。剩下的工作就不用多說了。
?
[cpp]?view plaincopy- int?MinimumRepresentation(char?*s,?int?l)??
- {??
- ????int?i?=?0,?j?=?1,?k?=?0,?t;??
- ????while(i?<?l?&&?j?<?l?&&?k?<?l)?{??
- ????????t?=?s[(i?+?k)?>=?l???i?+?k?-?l?:?i?+?k]?-?s[(j?+?k)?>=?l???j?+?k?-?l?:?j?+?k];??
- ????????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???i?:?j);??
- } ?
http://acm.timus.ru/problem.aspx?space=1&num=1423
這個題目可以練練手,也可用KMP?
轉載于:https://www.cnblogs.com/PegasusWang/archive/2013/05/28/3104851.html
總結
以上是生活随笔為你收集整理的字符串循环同构的最小表示法(转)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 剑南春多少钱一瓶啊?
- 下一篇: SQL 2005 删除带有默认值约束的列