這是一道dp題,然後來想想怎麼表示狀態,對答案有影響的就是a串的第i個字元,b串的第j個字元,和k個子串,簡單來說就是和選取的字元和子串的數量有關.
那麼設 f[i][j][kk]表示在a串的前i個字元中選kk個子串匹配b串的前j個字元的方案數.求方案數可以採用加法原理,考慮a串的第i個字元,那麼這個字元的決策只有取或不取,很明顯,加法原理,把不取的方案數和取的方案數加起來就可以,但是狀態的定義並不能看出這個字元到底取不取,或者說並不能推出結果來,怎麼辦呢?
那麼就用乙個陣列s[i][j][kk]來表示在a串的前i個字元中選kk個子串匹配b串的前j個字元的方案數,a串的第i個字元會被取到.那麼這個s陣列該怎麼推出來呢?可以發現,如果取第i個字元也有2種可能,因為kk是一定的,第i個字元可能和第i-1個字元合併成乙個子串,那麼從s[i-1][j][kk]轉移過來,也可能不和第i-1個字元合併成乙個子串,那麼就要新開乙個子串,故kk一定從kk-1轉移過來,根據加法原理,
那麼s[i][j][kk] = s[i-1][j-1][kk] + f[i-1][j-1][kk-1].
還有乙個問題,f陣列該怎麼推呢?根據之前分析的,把不取和取的加上來即可,即f[i][j][kk] = s[i][j][kk] + f[i-1][j][kk],其實可以發現,f陣列就相當於字首和陣列.
還有乙個問題:這是乙個三維的狀態轉移方程!空間不一定開的下,再看資料範圍,這絕對mle,怎麼辦?注意到i只能從i或i-1轉移過來,可以想到滾動陣列,滾動陣列有乙個比較好些的寫法就是把第一維全部加上&1,或者乾脆弄兩個變數處理完一組資料就交換即可.
#include
#include
#include
#include
using
namespace
std;
int n, m, k;
long
long f[2][205][205], s[2][205][205];
char a[1005], b[205];
const
int mod = 1000000007;
int main()
swap(now, last); //一定要變,否則就是一直自己跟自己轉移.
}printf("%lld\n", f[last][m][k]);
return
0;}
NOIP2015解題報告
day1.當時的zxn很弱,弱到連dfs都調不明白就開始去noip。現在他會了dfs,二分答案,求lca,bfs,拓撲排序。所以他回去填noip2015的題解坑。t1.我現在依然不知道除了這種尾遞迴式的寫法之外還有啥別的寫法 偽 void dfs int i,int j,int x 咳我好像現在明白...
noip2015運輸計畫解題報告
公元 2044 年,人類進入了宇宙紀元。l 國有 n 個星球,還有 n 1 條雙向航道,每條航道建立在兩個星球之間,這 n 1 條航道連通了 l 國的所有星球。小 p 掌管一家物流公司,該公司有很多個運輸計畫,每個運輸計畫形如 有一艘物 流飛船需要從 ui 號星球沿最快的宇航路徑飛行到 vi 號星球...
NOIP2015子串題解
題目描述 有兩個僅包含小寫英文本母的字串a和b。現在要從字串a中取出k個 互不重疊 的非空子串,然後把這k個子串按照其在字串a中出現的順序 依次連線 起來得到乙個新的字串,請問有多少種方案可以使得這個新串與字串b相等?注意 子串取出的位置不同也認為是不同的方案。輸入第一行是三個正整數n,m,k,分別...