DP總結 字串 子串

2021-07-24 10:33:20 字數 2497 閱讀 8626

題目描述】

有兩個僅包含小寫英文本母的字串a和b。現在要從字串a中取出k個互不重疊的非空子串,然後把這k個子串按照其在字串a中出現的順序依次連線起來得到乙個新的字串,請問有多少種方案可以使得這個新串與字串b相等?注意:子串取出的位置不同也認為是不同的方案。

由於答案可能很大,所以這裡要求輸出答案對1,000,000,007取模的結果。

【樣例輸入1】

6 3 1

aabaab

aab【樣例輸出1】2

【樣例輸入2】

6 3 2

aabaab

aab【樣例輸出2】7

【樣例輸入3】

6 3 3

aabaab

aab【樣例輸出3】7

id="iframe_0.926966518862173" src="data:text/html;charset=utf8,%3cimg%20id=%22img%22%20src=%22'img');%20window.parent.postmessage(%7biframeid:'iframe_0.926966518862173',width:img.width,height:img.height%7d,%20'');%7d%3c/script%3e" frameborder="0" scrolling="no" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-style: none; border-right-style: none; border-bottom-style: none; border-left-style: none; border-width: initial; border-color: initial; width: 17px; height: 19px; ">

【資料規模與約定】

對於100%的資料:1≤n≤1000,1≤m≤200,1≤k≤m。

【解法】

還好吧……乙個dp……不過細節比較多,難度不小。

我們令f[i][j][k][0/1]表示a串用了前i個字元,b串已覆蓋前j個字元,目前為止已經選了k個子串,最後的0/1表示a串的這個字元選了沒有(0沒選,1選了)。

為了得出狀態轉移方程,我們分情況討論:

先看f[i][j][k][1](當前位選了),顯然當且僅當a[i]=b[j]的時候它才有意義,否則f[i][j][k][1]=0。

到這個狀態有三種方法:

1. 上一位沒有選,新開乙個子串

2. 上一位選了,延續這個子串

3. 上一位選了,但是仍然新開乙個子串

因此,我們有

f[i][j][k][1]=f[i-1][j-1][k-1][0]+f[i-1][j-1][k][1]+f[i-1][j-1][k-1][1]。

狀態轉移方程中的三項分別對應上述三種情況。注意,因為我們規定了a的這一位必須選(因為狀態的最後一維是1),所以所有前驅狀態一定是f[i-1][j-1][…][…]。

然後討論另一種情況:這個字元不選。

這個比較簡單,到這個狀態有兩種方法:

1. 上一位沒有選,現在仍然不選

2. 上一位選了,結束這個子串

因此,我們有

f[i][j][k][0]=f[i-1][j][k][0]+f[i-1][j][k][1]。

合起來就是

f[i][j][k][1]=f[i-1][j-1][k-1][0]+f[i-1][j-1][k][1]+f[i-1][j-1][k-1][1](a[i]=b[j])

f[i][j][k][1]=0(a[i]!=b[j])

f[i][j][k][0]=f[i-1][j][k][0]+f[i-1][j][k][1]

狀態轉移方程有了,邊界也容易確定:f[0][0][0][0]=1。至於最終答案,顯然是f[n][m][k][0]+f[n][m][k][1]。

這裡有o(nmk)個狀態,轉移是o(1)的,因此總複雜度o(nmk),完全夠用(畢竟常數不大)。

然後,注意一些可能越界的問題(j/k=0的時候不要j/k-1),再用滾動陣列壓掉第一維,就可以ac了。

總結最長公共字串問題一般需要考慮的點其實都包含在這道題裡面了。

就是 第 i 位 選還是不選。

選 或者 不選 可以 由 上乙個狀態中哪一種狀態得到。

fighting!

字串子串

定義變數 string this is a test 取字串長度,空格也算 從positon處提取字串,positon從0 開始.也可以認為是提取postion之後字串,不算position處 從position位置處取length長的字串.也可以 echo cut c 1 4,取1 4的字元,1 ...

VC中字串取子串總結

一。前言 程式中經常會遇到要處理用某些符號 如空格,或 t 等 分隔的字串的問題,我在此做了一些總結和比較。二。處理方法 1.用mfc cstring之find處理字串 以下方法將乙個字串分解後放到乙個cstringarray中 void extractstring cstringarray arr...

字串 判斷子串

給定兩個陣列s和t 只包含小寫字母 判斷s是否為t刪除若干字元後得到的子串。若單純判斷是否為子串,過程比較簡單,只需要設定兩個指標。public boolean issubsequence string s,string t if is s.length return true else retur...