POJ-2192 Zipper-DP-字符串

Zipper
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 17232   Accepted: 6131

Description

Given three strings, you are to determine whether the third string can be formed by combining the characters in the first two strings. The first two strings can be mixed arbitrarily, but each must stay in its original order.

For example, consider forming "tcraete" from "cat" and "tree":

String A: cat
String B: tree
String C: tcraete

As you can see, we can form the third string by alternating characters from the two strings. As a second example, consider forming "catrtee" from "cat" and "tree":

String A: cat
String B: tree
String C: catrtee

Finally, notice that it is impossible to form "cttaree" from "cat" and "tree".

Input

The first line of input contains a single positive integer from 1 through 1000. It represents the number of data sets to follow. The processing for each data set is identical. The data sets appear on the following lines, one data set per line.

For each data set, the line of input consists of three strings, separated by a single space. All strings are composed of upper and lower case letters only. The length of the third string is always the sum of the lengths of the first two strings. The first two strings will have lengths between 1 and 200 characters, inclusive.

Output

For each data set, print:

Data set n: yes

if the third string can be formed from the first two, or

Data set n: no

if it cannot. Of course n should be replaced by the data set number. See the sample output below for an example.

Sample Input

3
cat tree tcraete
cat tree catrtee
cat tree cttaree

Sample Output

Data set 1: yes
Data set 2: yes
Data set 3: no

Source

Pacific Northwest 2004

第一眼看到这个题目就想到用字符串模拟....自己嫩得跟什么似得.....后面问了学长...自己想了很久,然后这里给出详细结题报告: 个人觉得这个对于刚接触 dp 的人来说是一个比较好的经典题目,很有dp的思维(对于目前菜菜的我来说)

题意:给你三个字符串,A、B、C,问你A和B能否组成C,当然是有要求的,那就是所有组成C的字母一定要按照A和B的顺序来,不能乱,意思就是从C中按顺序把组成A(或B)的所有字母拿出来,剩下的就是B(或A)

分析: 首先给出详细分析如何得到dp状态转移方程,然后就是详细的实现过程(很多地方结合图形有利于理解分析)

首先,我们可以知道 C 的最后一个字母,要不是由 A的最后一个组成,要不就是B的最后一个组成,那么对于C的任意一位(这里说成)第 i + j 位要么就是由A的 i 位 或者 B 的 j 位组成,那么这个先给出 一个数组 dp[i][j] (它的行是由A的所有字母按顺序组成,列是B组成,比如题目的案例可以有以下图:

POJ-2192 Zipper-DP-字符串_第1张图片 ),它的值为 1 的时候表示 C 的 第 i + j 位 可以由A 的i 或者 B 的j 组成,为0 则表示不可以,那么我们对于整个的是否可以组成C我们可以用两个循环列举去组成的所有情况:for循环如下

for(i=1;i<=a;i++)//a表示A的长度
     for(j=1;j<=b;j++)//b表示B的长度

那么循环的过程就是求解dp这个二维方程组的过程,那么dp[i][j]的取值是怎么决定的呢?那么这里就涉及到 状态转移方程 dp[i][j] = ?

那么这里可以得到状态转移方程为:dp[i][j] = { (A[i] == c[i+j] && dp[i-1][j] == 1) || (B[j] == c[i+j] && dp[i][j-1]),那么为什么是这样转移的呢? 我们考虑dp[i][j] 的值得时候为 只是考虑如下两种情况(红色字标出的):

POJ-2192 Zipper-DP-字符串_第2张图片 那么为什么要这样搭配出状态转移呢?

可以用下面的图理解:

POJ-2192 Zipper-DP-字符串_第3张图片 由图可以知道,我们反过来就是得到dp[i][j]的思路

那么分析到这里,还有一个地方要注意,我们对于给出的那么dp[i][j]的二维数组前面的i=0的那一行和j=0的那一列空出来了,那就是要做边界处理的情况,我们要枚举每一种组成情况组成那么当然就有 c[i][j] i=0时 只有B的j组成c的情况。。。。

上马:

#include<stdio.h>
#include<string.h>

#define MAX 201

int dp[MAX][MAX];
char A[MAX],B[MAX],C[MAX*2];

int main()
{
  int T;
  int i,j;
  scanf("%d",&T);
  A[0]=B[0]=C[0]='0';
  for(int cas=1;cas<=T;cas++)  {   scanf("%s%s%s",A+1,B+1,C+1);//这里都从下标为1开始
  int a=strlen(A)-1,b=strlen(B)-1;

  for(i=1;i<=a;i++)//边界处理
   if(A[i]==C[i])	dp[i][0]=1;
   else            dp[i][0]=0;
   
  for(i=1;i<=b;i++)//边界处理
   if(B[i]==C[i])	dp[0][i]=1;
   else            dp[0][i]=0;

  for(i=1;i<=a;i++)
   for(j=1;j<=b;j++)
    dp[i][j]=((dp[i-1][j] && A[i]==C[i+j])||(dp[i][j-1] && B[j]==C[i+j]));

  printf("Data set %d: ",cas);
  if(dp[a][b])
   printf("yes\n");
  else
   printf("no\n");
 }
 return 0;
}

你可能感兴趣的:(dp,C语言,poj)