迴圈字串的最小表示法的問題可以這樣描述:
對於乙個字串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 plain
copy
int minimumrepresentation(char *s, int l)
} return (i < j ? i : j);
}
然後主函式 設定變數 = 所求的, 迴圈輸出, 不斷++, %=n就好了
**:
intgetmin
(char *s)
else
if(j + l +
1 > i) j = j + l +
1;else j = i + 1;}
return i < j ? i : j;
}int
getmax
(char *s)
else
if(i+k+
1 > j) i = i+k+
1;else i = j+
1;k = 0;}
}return i < j ? i : j;
}
字串的最小 大表示法
想象一下,把乙個字串圍成乙個圈,再次字元圈的任意一處斷開,將會得到乙個新的字串。在按此法生成的字串中,字典序最小的稱為原字串的最小表示法,最大的稱為原字串的最大表示法。那麼,我們怎麼求乙個字串的最小 大表示法呢?思路一 直接把這n個字串構造出來,然後排序。時間複雜度o n logn o nlogn ...
Vision 字串 最小(大)表示法
定義 求解問題 n個字串圍成乙個環,請從這個環中找出字典序最大 或最小 的 長度為n的字串 下標盡可能小 name 最小表示法 function 求解迴圈字串的最小字典序串 輸入引數 字串 字串長度 輸出引數 從某下標開始所得到的串字典序最小 下標最小 複雜度 o n include include...
字串最小表示法
最小表示法的定義 給定乙個字串,不斷地把最後乙個元素移到最前面,可得有n個這樣的字串 稱這n個字串是迴圈同構的 那麼最小表示就是這n個裡面字典序最小的乙個 怎麼求最小表示 wrong 最樸素的方法,把每乙個這樣的字串求出來,然後一一比較,找到字典序最小的迴圈同構串 然後資料範圍變大肯定會超時 那麼正...