1. 程式人生 > >國慶七天樂——第七天

國慶七天樂——第七天

detail 根據 第七天 生成 預處理 常用 最長子串 模式匹配 com

20171007

【字符串算法】

  1. 模式匹配----kmp

定義:next[i+1]是最大的j+1使得p[0~j]是p[0~i]的後綴

通過這個next數組來跳過某些冗余計算

作用:當模式串p的長度為j的前綴是長度為i前綴的後綴時,若文本串在i+1的位置失配,則指針可跳到j繼續嘗試與j+1位置匹配

如何求next指針

假設已求得前i個next,要求next[i+1]

設next[i]=j

若p[j]!=p[i]則使j=next[j]

若p[i]==p[j](或j出界)則next[i+1]=j+1(或0)

【復雜度】

可以證明或者從代碼中簡單地看出,kmp算法復雜度是O(n+m)

簡單匹配當不match的時候要回溯

Kmp算法只需要每次不匹配的時候跳一次next即可

復雜度降到了線性。

證明:

KMP 算法的時間復雜度由預處理和匹配兩部分組成

外層的 i 循環和內層的 j 循環是完全獨立的,時間復雜度可以單獨計算

i循環的時間復雜度明顯是 O(N)

j本身有加有減,但易知其下降的總次數不會超過增加的總次數( j 每次固定+1,但每次至少-1)

j 每次增加都隨i加1,故增加的總量為N,j下降的次數不會超過N

故 j 循環的時間復雜度也是 O(N)

總過程的時間復雜度為 O(N) 總時間復雜度是 O(N + M)

*********************例題*****************************

1.Poj2406

題意:給一個字符串,問字符串中有多少個循環

根據kmp中next數組的性質來求解

Next數組性質: p[0~j]是p[0~i]的後綴,A=B

顯然x=z,y=w

又因為y=z

所以x=y=z=w

……

由數學歸納法,得x為原串的最小循環節

2.NOI2014

題意:給定一個長為L的字符串(L<=100W),求一個num數組,num[i]表示長度為i的前綴中字符串S’的數量,其中S‘既是該前綴的前綴也是該前綴的後綴,且|S‘|*2<=i

Kmp變式

定義由i=next[i]轉移到-1的步數是dep[i]

從i跳到j<=i/2的位置,num[i]=dep[j] 想想為什麽?

然後就兩次kmp就好了

【字符串哈希】

字符串具有離散性強,長度大等特點,不易比較

如果給每個字符串一個數值做標簽,比較的時候直接比較這個標簽就能確定字符串是否匹配。

這個標簽就是字符串HASH函數

常用的HASH函數(BKDR HASH):

也有其他花式HASH函數,在此不一一例舉

參考資料: http://blog.csdn.net/djinglan/article/details/8812934

代碼:

常用的seed值: 31131131313131131313..

例如我們取x=131

求串s=pekinguniversity hash[s]

Hash[s]=p*131^15+e*131^14+…+y*131^0

那麽如果要在文本中找到串s,只用維護一個長度為16的子串的hash值並與hash(s)比較即可

維護長度為l的子串的hash

設已知hash[s[ i-l+1 ~ i ]]=h,要求h1=hash[s[ i-l ~ i+1 ]]

h1=(h-s[i-l+1]*seed^(l-1))*seed+s[i+1]*seed^0

******************例題*******************************

  1. 1. 口吃的外星人

題意:有一個外星人說的話裏包含很多重復的字符串,如ababa包含兩個aba,給定這個外星人說的一句話,找出至少出現m詞的最長字符串,字符串長度4e4

解法:二分答案L,判斷長度L的子串最多出現多少次

維護長度L的子串hash,若某hash值出現m次則有解

復雜度O(n log n)

【回文串manacher】

對稱軸可能是字符串中的一個位置或者一個間隙

避免重復操作?

把間隙變成字符!

aba —> #a#b#a#

abba —> #a#b#b#a#

Def: r[i]->以i為對稱軸的最長匹配半徑

e.g.

0 1 2 3 4 5 6

# a # b # a #

r: 0 1 0 3 0 1 0

r恰好是最長回文串的長度

(因為加了#的緣故,所以字符串長度變成了兩倍,而r是枚舉最長子串的半徑,所以r最長就是回文子串最長)

先定義兩個指針

Pos:一個回文串的對稱軸

Max_r:max(pos+r[pos])

情況1:i<max_r,取j為i關於pos的對稱位置

當r[j]+i>max_r時,i~max_r的一段必然可以匹配成回文串

而max_r+1的位置開始需要逐位匹配

Max_r=i+r[i],pos=I

情況2:i<max_r,取j為i關於pos的對稱位置

r[j]+i<=max_r

r[i]=r[j]

情況3:i>=max_r

從i開始往右逐位匹配,max_r=r[i]+i

***********************例題*************************

題目大意:

就是現在給出一個長度為 n 的字符串(1 <= n <= 10^6)和一個正整數K(1 <= K <= 10^12)

對於給出的長度為n的字符串如果其回文串的數量比K少則輸出-1, 否則輸出所有回文串中長度為奇數的最長的前K個回文串的長度的乘積, 結果對於19930726取模輸出

解法:

首先可以用manacher算法確定每個位置的回文半徑, 由於這裏只需要長度是奇數, 所以不需要再原來的字符串的相鄰兩個字符之間插入未出現的字符, 直接在首尾添加好不同字符之後盤一遍manacher算法, 對於位置i為中心的回文半徑R[i], 用dp[i]來表示相鄰長度的回文串的數量差分(其實就是一個常用的前綴和技巧, 因為這裏每次更新[1, R[i]]這個區間 + 1, 而只在所有更新完畢之後才查詢所以沒有必要使用樹狀數組, 直接根據每次更新的時候dp[1]++, dp[R[i] + 1]--, 最後後dp[1~i]的和就是最終ans[i]的值, 即長度為2*i - 1的回文串的數量,然後用快速冪就可以了

【考試2】

T1字符串

Manacher板子

T2動態規劃

狀態壓縮dp,估計深搜廣搜優化一下也能過

F(I,j,p)表示第i時間段選擇課程為j,此時combo為p的最大收獲量

Add是j狀態i時刻能獲得的收獲

當狀態與選課吻合時

F(I,j,p)=max{f(I-1,k,p-1)}+add (1<=p<=10)

當選課與狀態不吻合時

f(I,j,0)=max{f(i-1,k,p)+p*(p-1)/2}+add (0<=p<=10)

T3圖論

最小生成樹加dfs加貪心

因為邊是以億為單位的1e8數量級,而且不同邊價格不同,所以n-1條邊結果一定最優,所以買邊和訪問是分開的兩個問題。

先最小生成樹建邊,把花費*1e8加入答案。

Dfs計算訪問一顆子樹的時間T[i]和每顆子樹的費用和sum[i]

貪心,策略類似於國王遊戲

由於限制訪問次數,訪問子樹時必定先遍歷完一顆子樹再去訪問另一顆

那麽當存在兩顆子樹時,設T0,sum0,T1,sum1

若先訪問0,則1的等待時間和等待花銷已知,為t0*sum1

同理若先訪問1,則0的花銷為t1*sum0

當t0/sum0<t1/sum1時,先訪問t0更優

對每個點的子樹的ti/sumi排序

順序訪問子樹,轉化為子問題,此題得解。

國慶七天樂——第七天