動態規劃(其一)字串問題

2022-06-24 18:21:08 字數 2511 閱讀 4682

之前做過相關總結,但是沒有今天二次看的時候這麼深入

經過自己這兩天的理解和實踐後,個人再對動態規劃、貪心、dfs、遞迴的關係再做乙個總結;

首先,dfs和貪心、遞迴的關係:

dfs是一種遍歷方式,而遞迴是程式的一種書寫方式,貪心則是一種演算法策略。

三者的關係可以總結為:貪心可以通過dfs來實現,而dfs可以通過遞迴來更簡便的實現;

例如在經典的找零錢和算月餅問題,很簡單的就是通過dfs來優先搜尋一些滿足條件的值,類似於深度遍歷樹的感覺;

而若是使用貪心演算法,則每次dfs搜尋,都先搜尋值比較大的分支,從而使得區域性最大變為整體最大;

值得一提:圖論中的最短路徑本質就是貪心,但是這個貪心得到的肯定是最優解,並且作者已經給出了證明;

其次:貪心和動態規劃得關係:

兩個壓根就不是乙個東西,是兩種解題思想,只不過遍歷結構相似;

最大的區別:貪心自上而下,未必是全域性最優解;動態規劃自下而上,肯定是全域性最優解;

對於典型的暴力列舉和dfs來說,哪怕是dfs剪枝,都不可避免地產生一些重複計算,在無向圖的遍歷中也極為明顯。所以動態規劃自底向上來進行計算,先把子問題算出來,後續的所有計算都在先前的計算之上,類似於一層一層打地基建樓房。從而保證從底部找到的最優解必定會構成整體最優解;

而貪心演算法未必,但是可以解決不少動態規劃問題,但也只侷限於oj中。唯一例外的可能就是01揹包問題,是沒法用貪心演算法解決的,這個後續再說。

但是儘管可以解決,也會造成tle或者爆記憶體;原因還是貪心如果進行類dfs便利的時候,複雜度往往在m的n次方左右,其中m是選擇情況,n為問題規模;

對於動態規劃來說,最主要的就是建模,也就是怎麼構建轉換方程和dp陣列,這個往往根據實際問題有關;

目前自己見到的題無非以下幾種:字串問題,序列問題,揹包問題;

其中動態規劃最難的有三個地方:

1.dp陣列的建造;

2.dp陣列邊界的確定;

3.dp陣列如何從邊界向上構建;

最長回文字串問題:

需要構建二維dp陣列,其中dp[i][j]為布林值,代表索引i-j構成的子串是否是回文串,在構建dp陣列的時候進行統計;

其中狀態轉換方程為:當s[i]==s[j]相等時 dp[i][j]=0 (dp[i+1][j-1]=0)或者dp[i][j]=1 (dp[i+1][j-1]=1)

自己做的時候踩了乙個坑,誤把dp[i][j]=n,n代表i-j間回文子串長度,最後直接得到dp[0][s.size()-1]即為回文子串長度,但是這樣是錯誤的;

究其原因是對於asbbda來說,由於s和d不相等,所以相對dp值為0,儘管a和末尾a相等,但是也不能在其基礎上+1變成1,因為中間不能構成回文子串;簡而言之,只要中間不是回文子串,外部就不可能是回文子串;

最後難點也在於如何從邊界向上構造,示例思想是通過字元長度區間來進行構造,也就是len=1、2、3的子串,遍歷len的最大長度,使得dp[i][i+len]挨個進行構造;

注意,序列中連續和不連續可能會導致dp陣列的遍歷有不同的理解;

典型的動態規劃問題之一,主要是給出序列來找出最長的不下降序列。

之前用貪心做過相關的問題,從第乙個開始找最接近自己的元素,挨個標記進行遍歷,但是容易爆記憶體,並且複雜度奇高,最壞情況可能到達n*n次方。

如果用dp思想,則利用dp陣列一次就可以遍歷出來;

dp[i]代表以第i個元素結尾的序列。所以dp[i]可能出現兩種情況,自己就是乙個元素的序列,自己之前還有其他元素;

所以有狀態轉移方程:dp[i]=max(dp[j]+,1),注意,其中j從1~i-1;

在進行狀態轉移的時候需要進行j的列舉。原因:3,4,1,2,5;當遍歷到dp[5]的時候,前面有多個非遞減序列,所以要進行列舉,來找到最長的路徑;

也是序列dp問題的典型題;

dp陣列可以構建為dp[i],當選擇第i為作為連續序列中的最後乙個元素。所以dp[i]=max(dp[i-1]+num[i],num[i])也就是兩種情況:加上第i個數,反而小,還不如讓這個數作為新序列的第乙個元素;

所以一次遍歷完之後,記錄拆分路徑,就可以一次得到多個最大序列,之後遍歷找出最大的序列即可;

//這道題目記錄路徑的方式可以著重學一下,很有建設性;

dp問題的經典問題,但是pat沒有例題,在以往的機試題見到了相關的問題;

dp陣列構建為2維,其中值得注意的是dp陣列代表的含義,代表1-i和1-j個序列的最大子列;

狀態轉移方程為:

dp[i][j]=dp[i-1][j-1]+1;(當a[i]==b[j])

max;(當a[i]!=b[j]) 

值得注意的是:

1.邊界問題:其中i,j從1號開始,則0號作為邊界。之所以這樣是因為空串和非空串不可能有公共子串,直接就是0;

2.地推方程問題:注意這種型別和回文子串的區別,回文子串要求連續,而最長公共子串行並不需要連續,所以只需要取最大值即可;

典型例題:

其實總而言之,還是要想著怎麼去劃分子問題,最後是能找到所有的基礎子問題——也就是dp邊界,確立dp陣列的機構;

其次,找到dp陣列的構造方式後,要想怎麼從遞推邊界向上推導;

字串(一) 字串Hash

今天開一手最不 tao 擅 yan 長的字串演算法 字串hash演算法。似乎提到字串的話,kmp應該是更為常見的一種,但是hash有它的優點,被犇們稱為 優雅的暴力 何謂hash?hash的中文稱為雜湊,這當然是音譯,直譯過來就是雜湊,或者也有叫預對映的。雜湊的作用就是通過某個特殊函式的對映,將任意...

第一字串 Trie Topology

bessie最近在玩字串。她發現通過改變字母的順序可以使一些字串排在其他所有的字串之前 按字典序從小到大排序 比如說,bessie找到了對於字串 omm moo mom 和 ommnom 她可以用標準的字母表把 mom 排在最前面,也可以用字母表 abcdefghijklonmpqrstuvwxyz...

演算法題(一) 字串

public static string submax string strarr else if max k system.out.println max return arrays.copyofrange strarr,start,end 1 給定兩個字串str1,str2。如果兩者字元種類和相...