字串的最小 大 表示法

2021-09-10 14:51:41 字數 1606 閱讀 8372

迴圈字串的最小表示法的問題可以這樣描述:

對於乙個字串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 最樸素的方法,把每乙個這樣的字串求出來,然後一一比較,找到字典序最小的迴圈同構串 然後資料範圍變大肯定會超時 那麼正...