日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

luogu P2679——子串

發布時間:2025/4/16 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 luogu P2679——子串 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目描述有兩個僅包含小寫英文字母的字符串 AAA 和 BBB 。現在要從字符串 AAA 中取出 kkk 個互不重疊的非空子串,然后把這 kkk 個子串按照其在字符串 AAA 中出現的順序依次連接起來得到一個新的字符串。請問有多少種方案可以使得這個新串與字符串 BBB 相等?注意:子串取出的位置不同也認為是不同的方案。 輸入輸出格式 輸入格式:第一行是三個正整數 n,m,kn,m,kn,m,k ,分別表示字符串 AAA 的長度,字符串 BBB 的長度,以及問題描述中所提到的 kkk ,每兩個整數之間用一個空格隔開。第二行包含一個長度為 nnn 的字符串,表示字符串 AAA 。第三行包含一個長度為 mmm 的字符串,表示字符串 BBB 。輸出格式:輸出共一行,包含一個整數,表示所求方案數。由于答案可能很大,所以這里要求輸出答案對 100000000710000000071000000007 取模的結果。輸入輸出樣例 輸入樣例#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=1; 對于第 2 組至第 3 組數據:1≤n≤500,1≤m≤50,k=2; 對于第 4 組至第 5 組數據:1≤n≤500,1≤m≤50,k=m; 對于第 1 組至第 7 組數據:1≤n≤500,1≤m≤50,1≤k≤m; 對于第 1 組至第 9 組數據:1≤n≤1000,1≤m≤100,1≤k≤m; 對于所有 10 組數據:1≤n≤1000,1≤m≤200,1≤k≤m。 題面

?如題,我們分析一下。好像是一個dp???

對啊好像是。

那么想一下狀態;

dp[ i ][ j ][ k ]表示a串匹配到i的位置,b串匹配到j的位置,用了k個子串的方案數;

當a[i]==b[j]時,則有兩種情況:

一是可以自己成為一個子串:dp[i-1][j-1][k-1];

二是和前一個湊成一個子串:dp[i-1][j-1][k];

那么轉移方程就為

dp[ i ][ j ][ k ]=(dp[i-1][j-1][k-1]+dp[i-1][j-1][k])%mod;

可是好像有一些問題,就是這一個位置就算他們相等也可以不選,跳過;

那么我們就要重設狀態了;

dp[ i ][ j ][ k ][0/1]表示當前這個字符選(0)/選不選無所謂( 1 )的方案數;

但是我們看一下數據范圍1000*200*200*2*4(int的字節)/1024/1024=305.17578125>128;

肯定是開不下的,那我們嘗試把第一維抹掉;

dp[ j ][ k ][0]表示b字符串中匹配到j這個位置,用了k個子串,并且當前這個位置一定選的方案數;

dp[ j ][ k ][1]表示b字符串中匹配到j這個位置,用了k個子串,并且當前這個位置不一定選的方案數;

當a[i]==b[j]時,dp[ j ][ k ][0]仍舊有兩種轉移

一是可以自己成為一個子串,不管前面一個選或不選:dp[j-1][k-1][1];

二是和前一個湊成一個子串:dp[j-1][k][0];

那么dp[ j ][ k ][1]的轉移為

一當前這一位取:dp[ j ][ k ][0];

二當前這一位不取:dp[ j ][ k ][1];

如果a[ i ]!=a[ j ]

那么當前b里這一位選的方案數肯定是0:dp[j][k][0]=0;

最后只需要輸出dp[b字符串的長度][子串總數][1]即可,因為最后一位可取可不取;

既然是dp方程,肯定要有初值的啊

dp[0][0][0]=dp[0][0][1]=1;(某神犇傳授的經驗,一般求方案數的dp,邊界條件都是1)

然后就結束了;

感謝葉犇犇的指導;

貼一發 ↑ 神犇的博客

#include<cstdio> #include<algorithm> #include<cstring> #include<iostream> using namespace std; const int mod=1000000007; char a[1200],b[210]; int n,m,tot; int dp[210][210][3]; int main() {scanf("%d%d%d",&n,&m,&tot);cin>>a+1;cin>>b+1;/*for(int i=1;i<=n;i++)cout<<a[i]<<" ";cout<<endl;for(int i=1;i<=m;i++)cout<<b[i]<<" ";*/dp[0][0][0]=dp[0][0][1]=1;//第三維是零表示這一位必選,是1表示選不選都行; for(int i=1;i<=n;i++)for(int j=m;j>=1;j--)for(int k=1;k<=tot;k++){if(a[i]==b[j]){dp[j][k][0]=(dp[j-1][k][0]+dp[j-1][k-1][1])%mod;//獨自成一串(dp[j-1][k-1][1])或者是與前面成一串 ( dp[j-1][k][0]); dp[j][k][1]=(dp[j][k][0]+dp[j][k][1])%mod;//當前這一位取的話就是dp[j][k][0],不取的話就是dp[j][k][1](這其實是從上一位轉移過來的); }elsedp[j][k][0]=0; }printf("%d",dp[m][tot][1]);return 0; } 標程

轉載注明來源,謝謝;

轉載于:https://www.cnblogs.com/royal-8/p/9084860.html

總結

以上是生活随笔為你收集整理的luogu P2679——子串的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。