題目大意:
有n個有01組成的字串,每個字串都代表乙個項鍊,那麼該字串就是乙個環狀的結構,求可以經過迴圈旋轉,最後不同的串有多少個。
演算法思想:
將每個字串轉換成最小串,然後放在set裡面去重。
最小表示法:
迴圈字串的最小表示法的問題可以這樣描述:
對於乙個字串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
實際上,如果s[i+k] > s[j+k] ,那麼s[i + k]就不可能是最小表示的下標,所以此時直接令i = i + k +1;
優化後的演算法,也就是說最小表示法,實際上是用 i, j兩個指標去找最小的位置。
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(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 的值。
(4) 進一步的優化,例如:i要移到i+k+1時,如果i+k+1 <= p2的話,可以直接把i移到 j+1,因為,j到j+k已經檢驗過了該字首比以i到i+k之間任何乙個位字首都小;j時的類似,移動到i+1。
第4步暫時還沒有看懂,先給出模板吧
#include#include#include#includeusing namespace std;
int len;
const int maxn = 10000 + 10;
char s[maxn];
char t[maxn];
setst;
int minrepresentation(char *s)
} return min(i,j);
}void getset(char *s)
int main(){
int n;
while(scanf("%d",&n)!=eof ){
st.clear();
for(int i=0;i
HDU 2609 How many (最小表示法)
題意 n 10000個字 符串,l 100,可以 滾動,如 果滾動後 相同,算 同乙個,問有多少 個不同的 串 分析 最小 表示法表 示一下每 個字串 然後丟 到set 裡,輸出 個數就好 了 created by taosama on 2015 10 30 pragma comment linke...
HDU2609 How many(最小表示法)
題意 給n個長度100以內的字串,如果兩個字串迴圈移位可以得到相等的結果,那麼就認為這兩個字串相等。求這n個字串一共包含多少個不同的字串。思路 顯然每個串迴圈移位得到的最小值是一定的,可以先用最小表示法處理出每個字串的最小值,排個序,然後只需比較相鄰的兩個串是否相同就行了。include inclu...
HDU 2609 How many 最小表示法
題目傳送門 題意 給出n個01串,通過迴圈可以相同的串算一類,求一共有幾類串。思路 暴力,把所有串都變成最小表示法,然後排個序掃一遍就行了。ac code include include include include include include using namespace std cons...