題目連接:http://acm.hdu.edu.cn/showproblem.php?pid=5707php
題意:ios
給你三個字符串 S1, S2, S3, 讓你判斷 S3 是否剛好由字符串 S1 和 S2組成, S1 爲 S3 的子串, S2 也爲 S3 的子串, 能夠不連續.
spa
思路:code
設 dp[i][j] 表示字符串 S3 的前 i + j 位是否能夠由字符串 S1 的前 i 位以及字符串 S2 的前 j 位組成. dp[i][j] = 1 表示能夠, dp[i][j] = 0 則表示不能夠.
blog
則 dp[i][j] 能夠由 dp[i - 1][j] 和 dp[i][j - 1] 轉移過來.若是 dp[i][j] 由 dp[i - 1][j] 轉移而來,那麼應該知足:
ci
dp[i - 1][j] 是合法狀態( 即 dp[i - 1][j] = 1 ) 且 S1的第 i 個字符必須等於 S3 的第 i + j 個字符.字符串
若是 dp[i][j] 由 dp[i][j - 1] 轉移而來, 那麼應該知足:
get
dp[i][j - 1] 是合法狀態( 即 dp[i][j - 1] = 1 ) 且 S2 的第 j 個字符必須等於 S3 的第 i + j 個字符.string
綜上就能夠獲得狀態轉移方程:it
i == 0 && j == 0 : dp[i][j] = 1; //顯然空串能夠由兩個空串組成,是合法狀態. 除此以外其餘狀態的初始化應該爲 0
i != 0 && j == 0 : dp[i][j] = dp[i - 1][j] && S1[i - 1] == S3[i + j - 1] //字符串下標從零開始
i == 0 && j != 0 : dp[i][j] = dp[i][j - 1] && S2[j - 1] == S3[i + j - 1]
i != 0 && j != 0 : dp[i][j] = ( dp[i - 1][j] && S1[i - 1] == S3[i + j - 1] ) || ( dp[i][j] = dp[i][j - 1] && S2[j - 1] == S3[i + j - 1] ) //二者知足其一便可
除此以外, 題目中還要求 S3 必須剛好由 S1 和 S2 組成, 則除知足 dp[ len(S1) ][ len(S2) ] == 1 以外, len(S1) + len(S2) == len(S3) 也應必須成立.
代碼:
1 #include <iostream> 2 #include <cstring> 3 4 using namespace std; 5 typedef long long LL; 6 const int MAXN = 2000; 7 int dp[MAXN + 3][MAXN + 3]; 8 9 int main() { 10 ios_base::sync_with_stdio(0); cin.tie(0); 11 string s1, s2, s3; 12 while(cin >> s1 >> s2 >> s3) { 13 dp[0][0] = 1; //dp[0][0] 爲合法狀態 14 unsigned int i, j; 15 for(i = 0; i <= s1.length(); i++) { 16 for(j = 0; j <= s2.length(); j++) { 17 if(i && j) dp[i][j] = 0; //除 dp[0][0] 以外 其餘狀態的初始化 18 if(i) dp[i][j] = dp[i - 1][j] & (s1[i - 1] == s3[i + j - 1]); //因爲非0即1,因此能夠按位與 19 if(j) dp[i][j] |=dp[i][j - 1] & (s2[j - 1] == s3[i + j - 1]); // 「 |= 」 是由於 倆個轉移狀態知足其一就可 20 } 21 } 22 cout << ( (dp[i - 1][j - 1] && i + j - 2 == s3.length() ) ? "Yes":"No") << endl; 23 } 24 return 0; 25 }