KMP專題【完結】

轉自:http://blog.csdn.net/chenguolinblog/article/details/16857765


第一題 hdu 1711 Number Sequence

點擊打開hdu 1711

思路:

1 kmp是用來匹配字符串,只能夠匹配單一的字符串
2 kmp的算法的過程:
  1:假設文本串的長度爲n,模式串的長度爲m;
  2:先例用O(m)的時間去預處理next數組,next數組的意思指的是當前的字符串匹配失敗後要轉到的下一個狀態;
  3:利用o(n)的時間去完成匹配;

3 時間複雜度爲o(n+m)即o(n);

點擊查看代碼


第二題 hdu 1686 oulipo

點擊打開hdu 1686

思路:

1 題目要求的是給定一個模式串個一個文本串,求出模式串在文本串中出現幾次
2 典型的KMP問題,只要套上模板即可。

點擊查看代碼


第三題 hdu 2087 剪花布條

點擊打開hdu 2087

思路:

1 題目要求的是給定一個文本串和給定一個模式串,求文本串中有幾個模式串。
2 注意文本串爲"aaaaaa",模式串"aa"的時候,ans = 3 而不是5。

點擊查看代碼


第四題 hdu 3746 Cyclic Nacklace

點擊打開hdu 3746

思路:

1 題目要求的是給定一個字符串,問我們還需要添加幾個字符可以構成一個由n個循環節組成的字符串。
2 可知我們應該先求出字符串的最小循環節的長度:假設字符串的長度爲len,那麼最小的循環節就是cir = len-next[len] ; 如果有len%cir == 0,那麼這個字符串就是已經是完美的字符串,不用添加任何字符;如果不是完美的那麼需要添加的字符數就是cir - (len-(len/cir)*cir)),相當與需要在最後一個循環節上面添加幾個。
3 如果cir = 1,說明字符串只有一種字符例如“aaa” ; 如果cir = m說明最小的循環節長度爲m,那麼至少還需m個;如果m%cir == 0,說明已經不用添加了

點擊查看代碼


第五題 hdu 1358 Period

點擊打開hdu 1358

思路:

1 題目要求的是給定一個長度爲n的字符串,求出字符串的所有前綴字符串中該字符串剛好由k個最小循環節夠成,由於題目要求k最大那麼就是這個循環節最小
2 只要先求出next數組,然後去枚舉所有的前綴找到滿足的輸出長度和k

點擊查看代碼


第六題 hdu 2203 親和串

點擊打開hdu 2203

思路:

1 題目要求的是給定字符串s1 和 s2,問s1能否通過移位得到使得s2包含在s1裏面。
2 很顯然的kmp的模板題,只須在s1後面在添上一個s1即可。這裏特別注意strcat的使用
3 strcat函數,函數的原行strcat(char *s , char *p);注意這裏的s和p所指內存區域不可以重疊且dest必須有足夠的空間來容納src的字符串;所以假設s = “abc”,現在想得到“abcabc”那麼不能直接的strcat(s , s),而是先用一個tmp數組存儲s,即strcpy(tmp , s , sizeof(s)) , 然後在strcat(s , tmp);

點擊查看代碼


第七題 hust 1010 The Minimum Length

點擊打開hust 1010

思路:

1 題目要求的是,有一個字串A,現在利用A組成了一個新的字符串AAAAA...,現在從這個新的字符串的兩個不同位置剪下去得到字符串B,問A的最小長度
2 由於B裏面的字符都是來自A,那麼如果要A最小那麼最小值就是等於B的最小循環節。
3 直接對B求最小循環節

點擊查看代碼


第八題 poj 2406 Power Strings

點擊打開poj 2406

思路:

1 題目要求的是給定一個字符串找到最小循環節的個數,但是這裏有個限制的地方就是如果這個字符串不是剛好由n個最小循環節組成那麼就認爲一整串纔是一個循環節
2 題目說了輸入的字符是可打印的,所以應該用gets讀入,判斷終止的時候用strcmp。

點擊查看代碼


第九題 poj 2752 Seek the Name, Seek the Fame

點擊打開poj 2752

思路:

1 題意要求的找出滿足既是字符串的s的前綴又是後綴的字串輸出該字串的長度。
2 先看看next數組的含義:
   1:next數組只和模式串本身有關和文本串是無關的,因爲next表示的是當匹配失敗後模式串要回溯到哪個位置。
   2:next數組存儲的數據是用來當模式串與主串不匹配的時候要模式串回退到第幾個字符與主串再重新匹配,我們知道KMP算法的主串是不回朔的,當不匹配的時候我們不是退回到開始位置重新匹配,而是利用已經匹配的結果將模式串回朔到下一個位置,這個位置比開始位置更近一步;
簡單的說就是next[ j ]的值保存的是當模式串中第 j 個字符與主串第 i 個字符不匹配時候,模式串中的哪個字符 重新與主串第 i 個再匹配,這樣總的字符比較次數比從開始位置比較的次數就少了。
   3:next[j]存儲的就是模式串前j個字符裏前綴和後綴最大的匹配長度;也就是有j = next[j] ; 假設有模式串“abcabx”,那麼next[5] = 2就是前5個字符裏前綴和後綴匹配最長的長度爲2即“ab”;那麼就是說如果next[len] = ans , 整個串的前綴和後綴最長匹配的長度就是ans,上面的字符串“abcabx”的最長匹配就是0。
   4:在模式串與標準串進行匹配時,指向他們的指針分別爲j、i;當p[j]!=s[i]時,j直接變爲next[j],新的p[j]繼續與s[i]比較,如果不相等繼續進行此操作……那麼數組next[j]同樣反映了,在模式串p的第j個位置之前,p[0]~p[next[j]-1]與p[i-next[j]]~p[i-1]這兩段是完全一樣的。假設模式串爲“abcdabx”,手動模擬即可知道。

點擊查看代碼


第十題 poj 3080 Blue Jeans

點擊打開poj 3080

思路:

1 題目要求的是給定m個DNA序列,每個DNA序列長度固定爲60,問m個DNA序列的最長的公共子串
2 初看題目無從下手,但是你仔細研究發現是要找m個序列的公共子串,那麼這個子串必定存在於第一個DNA序列裏面。這個時候就可以想到去枚舉第一個DNA序列的所有子串,由於長度爲60那麼最多3600個子串,由於m最多10個;所以算一下複雜度就是0(3600*n*m),n是60和m最大10,那麼這樣的複雜度是可以接受的。

點擊查看代碼


第十一題 hdu 2594 Simpsons’ Hidden Talents

點擊打開hdu 2594

思路:

1 題目要求的是給定兩個字符串s1 , s2找到s1的最長前綴等於s2的後綴
2 很明顯就是next數組的應用,我們知道next[j] = len,表示的前j個字符裏面前綴和後綴的最長匹配長度爲len。那麼我們只要合併兩個字符串然後求next數組即可。
3 注意以下的數據
abcabcabcabc
abcabcabcabcabc
輸出 12
abcabc
abc
輸出 3
我們知道如果合併了s1和s2的話,那麼求出來的最長的長度是24 和 6顯然是不行的,因爲我們忽略了一個地方就是求出的最長的前綴的長度是不能超過
s1和s2的長度的,所以求出最長前綴長度後應該進行討論。

點擊查看代碼


第十二題 hdu 3336 Count the string

點擊打開hdu 3333

思路:

1 題目要求的是給定一個字符串s,求字符串s的所有的前綴在s的匹配的次數之和mod10007.
2 很明顯n<= 200000,分析一下那麼就要n個前綴如果每一個前最都去匹配s的話複雜度就是o(n^2),那麼肯定是TLE的,所以要考慮另外的思路
3 我們知道next[j] = len,表示的是在前j個字符裏前綴和後綴的最大的匹配的長度爲len,所以根據next數組的性質,我們只要去枚舉j的值從n->1,爲什麼要從n開始而不是1開始呢,這裏因爲是要求前綴的匹配數而不是後綴;
4 求sum的時候注意每一步都有可能超過範圍,所以就要求一次sum同時取模一次。

點擊查看代碼


第十三題 hdu 4300 Clairewd’s message

點擊打開hdu 4300

思路:

1 題目要求的是給定一個不完整的由n個字符構成的字符串並且字符串有密文和明文兩部分組成,現在要求完整的字符串。
2 很明顯密文的長度不確定,現在又要求最短的字符串長度。由於在完整的字符串中密文和明文的長度是一樣的,那麼輸入的字符串中至少有(n+1)/2是密文,所以我們假設密文後面的都是明文,那麼我們將這些明文轉化爲密文後求next數組就可以知道前綴和後綴的最大的匹配數,那麼如果匹配數越大就說明總的串的長度就越小。
3 但是有個地方需要注意,輸入的字符串長度爲n,那麼至少(n+1)/2爲密文,那麼明文最多爲tmp = n-(n+1)/2,所以next[n]的最大值是不能超過tmp的,如果超過了那麼就另next[len] = tmp即可,說明已經最大了

點擊查看代碼


第十四題 hdu 1238 Substrings

點擊打開hdu 1238

思路:

1 題目要求找到一個子串x,滿足x或x的逆串是輸入的n個字符串的子串,求最大的x,輸出x的長度
2 題目的n最大100,每一個字符串的最大長度爲100,那麼暴力枚舉子串就是o(n^2)才10000肯定是不會超時的,但是由於這裏涉及到了逆串的問題,所以我們應該還要求出n個子串的逆串,然後在求最大的x。

點擊查看代碼


第十五題 hdu 2328 Corporate Identity

點擊打開hdu 2328

思路:

1 題意要求最長的公共子串,由於每一串的長度最長不超過200,所以可以選擇暴力枚舉最短的單詞的子串來求出ans
2 利用kmp來匹配

點擊查看代碼


第十六題 hdu 3374 String Problem

點擊打開hdu 3374

思路:

1 題目要求給定一個字符串求出最小和最大表示的rank和出現的times。
2 如果直接暴力枚舉n 最大10^6肯定TLE,所以這了應該要用到的是求解一個字符串的最小和最大表示,然後利用kmp去匹配查找出現的次數
3 在利用kmp匹配的時候應該要注意不能多算,比如有abcder,那麼用abcder去匹配abcderabcder的時候就有兩次的匹配結果,但實際上這裏只有一個,所以這個地方要注意。

點擊查看代碼


第十七題 hdu 2609 How many

點擊打開hdu 2609

思路:

1 題目要求的是給定n個字符串,找出不同的字符串的個數。由於題目說了,字符串可以進行變換,也就是如果兩個字符串相同那麼它們的最小表示是相同的。
2 只要求出所有字符串的最小表示,然後利用set存儲,最後set的元素個數就是最後的ans

點擊查看代碼


第十八題 fzu 1901 Period II

點擊打開fzu 1901

思路:

1 題目要求的找到所有滿足S[i]=S[i+P] for i in [0..SIZE(S)-p-1]的前綴,並且長度爲p。利用上面的式子可以等價的得到等式s[0,len-p-1] = s[p , len-1].
2 給個next數組的性質
   假設現在有一個字符串爲ababxxxxabab。那麼求出的next數組爲00012001234,那麼前綴和後綴最長的匹配數是4,然後下一個前綴和後綴匹配長度爲next[4] = 2 , 然後下一個爲next[2] = 0。
   所以有一個結論就是,假設當前求出的字符串的前綴和後綴的最長的匹配的長度爲len,那麼下一個滿足的前綴和後綴互相匹配的長度爲next[len]...依次
3 觀察一下上面的等式,我們發現並不是我們所熟悉的前綴和後綴匹配的等價式。那麼我們現在來看這個樣列
            f z u f z u f z u f   長度爲10
next    000 01 2 3 456 7
那麼根據next數組就得到前綴和後綴的匹配長度依次爲 7 4 1 0 ,那麼這時候看看題目的p的可能長度爲 3 6 9 10,那麼有沒有發現規律。
點擊查看代碼

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章