KMP hash(好題,對next陣列的理解加深)

2021-09-29 16:29:37 字數 1337 閱讀 1612

題目鏈結

給出乙個字串,找出乙個子串既是它的字首,也是它的字尾,還是乙個非字尾也非字首的子

題目分析:

本來挺簡單的乙個題,最開始想複雜了,還用了字尾陣列,醉了。

這個題主要用的是kmp的next陣列,首先我們要了解next陣列的定義,next[i]表示以i為末尾的子串的字尾與能夠匹配的整個串的最長的字首。

然後我們可以知道字尾與字首的最長相同的長度,現在是滿足字尾和字首的最長子串的情況。

然後我們利用hash除了以最後乙個字元結尾的情況所有的與字首匹配的長度。

最後我們利用next陣列的性質,如果當前的匹配的長度在hash表中找不到,那麼證明不存在非字首與非字尾的子串符合條件,那麼x=next[x],也就是跳轉到當前位置失配的重新匹配的位置(免去重複匹配的部分),也就是小於當前情況的最大的子串的字尾和字首匹配的情況,然後再查hash表。知道找到答案為止,找不到答案證明不存在解。 

如圖x2為x1失配時下一步將要用來對比的點,此時說明字首w1和字尾w2是最長的相同的前字尾,接下來要找有沒有既不是字首也不是字尾的一段,這樣就推出x3,原因是如果x3存在,那麼字首w3和字尾w4是最長的相同的前字尾,那麼w4就符合要找的那一段,因為它既和字首w3相同,又和字尾w5相同(原因是w1和w2相同);

#include#include#include#include#include#include#include#include#includeusing namespace std;

typedef long long ll;

int hash_s[1000001];//hash[i]表示i點存不存在

char s[1000001];

int next_s[1000001];

//next_s[i]表示點i之前的字串最長相同的前字尾的字首的下乙個位置

ll getnext()

return len;

}int main()

//不能把next_s[len]加到hash表中,因為要找字串中間的一段

ll x=next_s[len];

//如果hash表中不存在next_s[x];

while(!hash_s[x]&&x)

if(!x)

else for(int i=0;i

cout<

return 0;

}

每日一題 數對

本題來自牛客網,為網易2019年校招題之一。點我跳轉 題目描述 牛牛以前在老師那裡得到了乙個正整數數對 x,y 牛牛忘記他們具體是多少了。但是牛牛記得老師告訴過他x和y均不大於n,並且x除以y的餘數大於等於k。牛牛希望你能幫他計算一共有多少個可能的數對。輸入描述 輸入包括兩個正整數n,k 1 n 1...

劍指offer 醜數(好題,思路)

題目描述 把只包含因子2 3和5的數稱作醜數 ugly number 例如6 8都是醜數,但14不是,因為它包含因子7。習慣上我們把1當做是第乙個醜數。求按從小到大的順序的第n個醜數。思路 似乎只能乙個個判過去。判斷是否為醜數的時候,求因子時迴圈停止的條件是到平方根為止。這麼做會超時 而且題目中應該...

2019校招真題 數對

牛牛以前在老師那裡得到了乙個正整數數對 x,y 牛牛忘記他們具體是多少了。但是牛牛記得老師告訴過他x和y均不大於n,並且x除以y的餘數大於等於k。牛牛希望你能幫他計算一共有多少個可能的數對。輸入描述 輸入包括兩個正整數n,k 1 n 10 5,0 k n 1 輸出描述 對於每個測試用例,輸出乙個正整...