1. 程式人生 > 其它 >python實現藉助360加固保程式碼實現批量、斷點再續等功能

python實現藉助360加固保程式碼實現批量、斷點再續等功能

技術標籤:動態規劃演算法區間動態規劃滾動陣列

題目描述

有兩個僅包含小寫英文字母的字串AA和BB。

現在要從字串AA中取出kk個互不重疊的非空子串,然後把這kk個子串按照其在字串AA中出現的順序依次連線起來得到一個新的字串。請問有多少種方案可以使得這個新串與字串BB相等?

注意:子串取出的位置不同也認為是不同的方案。

輸入格式

第一行是三個正整數n,m,kn,m,k,分別表示字串AA的長度,字串BB的長度,以及問題描述中所提到的kk,每兩個整數之間用一個空格隔開。

第二行包含一個長度為nn的字串,表示字串AA。

第三行包含一個長度為mm的字串,表示字串BB。

輸出格式

一個整數,表示所求方案數。

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

輸入輸出樣例

輸入 #1複製

6 3 1 
aabaab 
aab

輸出 #1複製

2

輸入 #2複製

6 3 2 
aabaab 
aab

輸出 #2複製

7

輸入 #3複製

6 3 3 
aabaab 
aab

輸出 #3複製

7

說明/提示

對於第 1 組資料:1≤n≤500,1≤m≤50,k=11≤n≤500,1≤m≤50,k=1;
對於第 2 組至第 3 組資料:1≤n≤500,1≤m≤50,k=21≤n≤500,1≤m≤50,k=2;
對於第 4 組至第 5 組資料:1≤n≤500,1≤m≤50,k=m1≤n≤500,1≤m≤50,k=m;
對於第 1 組至第 7 組資料:1≤n≤500,1≤m≤50,1≤k≤m1≤n≤500,1≤m≤50,1≤k≤m;

對於第 1 組至第 9 組資料:1≤n≤1000,1≤m≤100,1≤k≤m1≤n≤1000,1≤m≤100,1≤k≤m;
對於所有 10 組資料:1≤n≤1000,1≤m≤200,1≤k≤m1≤n≤1000,1≤m≤200,1≤k≤m。

思路:

剛開始想到的狀態是

dp[i][j][k]:a字串的前i個匹配b字串的前j個用k個子串。

但是,這樣還不夠,因為第i個字元的使用情況會影響第i-1個字元的使用情況。

為什麼呢?見下面的情況分析。

所以我們還需要一維來表示使用與否。 使用過用1,沒用過用0,即 dp[i][j][k][0/1].

當a[i]==b[j],那麼第i個字元可以使用也可以不使用。

使用:dp[i][j][k][1]=dp[i-1][j-1][k][1]+dp[i-1][j-1][k-1][0]+dp[i-1][j-1][k-1][1];

dp[i-1][j-1][k][1]:使用第i個字元並且跟前面的第i-1個字元連線成為第k個子串,所以第i-1個字元必須使用。(即跟第i個字元有關)

dp[i-1][j-1][k-1][0]、dp[i-1][j-1][k-1][1] :當第i個字元單獨成新的子串,那麼第i-1個字元可用可不用(即跟第i個字元無關)

不使用:

dp[i][j][k][0]=dp[i-1][j][k][1]+dp[i-1][j][k][0] (即跟第i個字元無關)

當a[i]!=b[j]時,

不使用:

dp[i][j][k][0]=dp[i-1][j][k][1]+dp[i-1][j][k][0] (即跟第i個字元無關)

使用:dp[i][j][k][1]=0;

綜上所述,有

if(a[i]==b[j]){

dp[i][j][k][1]=dp[i-1][j-1][k][1]+dp[i-1][j-1][k-1][0]+dp[i-1][j-1][k-1][1];

}

else dp[i][j][k][1]=0;

dp[i][j][k][0]=dp[i-1][j][k][1]+dp[i-1][j][k][0] ;

關鍵程式碼就好啦~

邊界值 dp[0][0][0][0]=1 dp[1][0][0][0][0]=1

假如開四維陣列,根據資料範圍有1000*200*200*2,很有可能卡空間。

通過轉移方程發現,每次i行都是通過i-1行更新得到的,所以我們只要開兩行的空間,來回使用,即滾動陣列就好了。

#include<bits/stdc++.h>
using namespace std;
char a[1005],b[205];
int dp[2][205][205][2];
const int mod=1000000007;
int main(){
	int n,m,k;
	scanf("%d%d%d%s%s",&n,&m,&k,a+1,b+1);
	dp[0][0][0][0]=1;
	dp[1][0][0][0]=1;
	for(int i=1; i<=n; i++){
        for(int j=1; j<=m; j++){
              for(int g=1; g<=k; g++){
                 if(a[i]==b[j]){
                    dp[i%2][j][g][1]=((dp[(i-1)%2][j-1][g-1][0]+dp[(i-1)%2][j-1][g-1][1])%mod+dp[(i-1)%2][j-1][g][1])%mod;
                 }
                 else{
                    dp[i%2][j][g][1]=0;
                 }
                  dp[i%2][j][g][0]=(dp[(i-1)%2][j][g][0]+dp[(i-1)%2][j][g][1])%mod;//不使用第i個
                }
           }
	}
    cout<<(dp[n%2][m][k][0]+dp[n%2][m][k][1])%mod<<endl;
	return 0;
}