禁止字串 白書P368

2021-10-08 21:27:42 字數 1823 閱讀 7479

考慮只由』a』, 『g』, 『c』, 『t』四種字元組成的dna字串。給定乙個長度為k的字串s,請計算長度恰好為n且不包含s的字串的個數。輸出個數mod 10009後的結果。

其中 1<=k<=100 1<=n<=10000

輸入n=3 k=2 s=「at」

輸出56

首先考慮最直觀的演算法就是:生成所有滿足條件的字串,但是字串個數可能高達4^n,顯然是行不通的。

接下來,與其在生成字串後在判斷它是否包含s,不如在搜尋的過程中,每在末尾新增乙個字元的時候,都確保其最後k個字元不包含s。可見最後k個字元之前的字元對以後的搜尋並無影響。所以,我們可以以剩餘字元的個數和最後k-1個字元為狀態進行動態規劃。

經過等價狀態的歸併後,其實只有k種狀態。即已經生成的字串的字尾和s的字首的匹配長度作為狀態。

思路:字串預處理+動態規劃。

在以下**中有兩個陣列next[i][j] 與dp[i][j] 分別代表了以上思路的兩個處理。

next[i][j]表示的是當前列舉到的字串的末尾的i個字元與s的前i個字元一樣的時候,當下乙個列舉到的字元是j(這裡j的取值是0~4 分別代表著「a, g, c, t」)的時候,其構造的新串末尾有i個字元與s的的前i個字元一樣的長度。

由以下例子可以更好地理解:

比如 s = 「atcg」 next[1][0] 代表的是當前串的末尾是a現在多加乙個a所以當前列舉到的串的末尾變成了aa, 與s相比其匹配數還是1;

所以: next[1][0] = 1;

同理 next[1][1] = 0;

對於s = 「atcg」 next為:

1 0 0 0

1 0 0 2

1 0 3 0

1 4 0 0

有時會有重複的情況請按匹配最大值儲存:例如 s = 「atcatcg」

如果當前列舉到的字串末尾是atcat 下一位列舉的是c的話那麼對於next[5][2] 可以等於3 也可以等於6, 這個時候按6算(按長的來算)。

dp[i][j]表示前i個字元最後面j個字元與s的前j個字元匹配的合法的字串的數目

狀態轉移方程:dp[i+1][j] += dp[i][m] ( 0 <= m <= k) ,在這裡並非累加所有的,要去掉那些違反題目條件的。

#include

using

namespace std;

const

int inf =

0x3f3f3f3f

;typedef

long

long ll;

int n,k;

string s;

const

char

*agct =

"agct"

;const

int maxn =

1009

;int dp[maxn]

[108];

int nex[maxn][5

];const

int mod =

10009

;void

init()

void

solve()

}for

(int i=

0;i}int ans =0;

for(

int i=

0;i) ans =

(ans + dp[n]

[i])

% mod;

cout << ans << endl;

}int

main()

}

禁止字串(大白p368)

考慮只由 a g c t 四種字元組成的dnf字串 給定乙個長度為k的字串s,計算長度恰好為n的且不包含s的字串的個數輸入結果對10009取模 1 k 100 1 n 10000 輸入 n 3,k 2,s at 輸出 56思路 字串預處理 動態規劃 在以下 中有兩個陣列next i j 與dp i ...

檢測是否含有禁止字串

檢測是否含有禁止字串 如果禁止字串出現次數為 5,測返回 true 引數說明 badwordlist 禁止字元列表 以 號隔開 str 被檢測字串 返回值 boolean 小男 2006 更新 no miss function checkbadword byval badwordlist,byval...

P1032 字串變換 字串

已知有兩個字串 a,b 及一組字串變換的規則 至多6個規則 a1 b1 a2 b2 規則的含義為 在 a 中的子串 a1 可以變換為 b1 a2 可以變換為 b2 例如 a abcd b xyz 變換規則為 abc xu ud y y yz 則此時,a 可以經過一系列的變換變為 b,其變換的過程為 ...