给出三个串a b c,问 c 是否能由 a b 串中的字符通过混合得到,要保持同一个串中两个字符的前后关系不变。
状态:f[i ,j] 表示长度为 i 且使用了b串 j 个字符(使用 a 串 i-j 个字符),布尔型,表示状态是否可达。
状态转移: f[i, j] = f[i-1, j] && f[i-1, j-1],对于边界f[0, 0] = true。
也可以令 f[i, j] 为使用了 a 串 i 个字符、b 串j个字符是否可达,如下:
1 /* 2 POJ 2192 Zipper 3 */ 4 # include <cstdio> 5 # include <cstring> 6 7 using namespace std; 8 9 # define N 200 + 10 10 11 char a[N], b[N], c[2 * N]; 12 char f[N][N]; 13 14 char dp(int n, int m) 15 { 16 f[0][0] = 1; 17 for (int i = 1; i <= n+m; ++i) 18 { 19 for (int j = 0; j <= i && j <= m; ++j) 20 { 21 if (i-j > n) continue; 22 if (!j) 23 { 24 f[i][0] = (f[i-1][0] & (c[i]==a[i])); 25 } 26 else if (i == j) 27 { 28 f[0][j] = (f[0][j-1] & (c[j]==b[j])); 29 } 30 else 31 f[i-j][j] = (f[i-j-1][j]&c[i]==a[i-j]) | 32 (f[i-j][j-1]&c[i]==b[j]); 33 } 34 } 35 return f[n][m]; 36 } 37 38 void solve(int icase) 39 { 40 int n, m; 41 scanf("%s%s%s", a+1, b+1, c+1); 42 n = strlen(a+1), m = strlen(b+1); 43 printf("Data set %d: ", icase); 44 dp(n, m); 45 puts(f[n][m] ? "yes":"no"); 46 } 47 48 int main() 49 { 50 int T; 51 52 scanf("%d", &T); 53 for (int i = 1; i <= T; ++i) 54 solve(i); 55 56 return 0; 57 }