【DFS或DP】Zipper

总时间限制:

1000ms
内存限制:
65536kB
描述
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".

输入
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.

输出
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.

样例输入
3
cat tree tcraete
cat tree catrtee
cat tree cttaree
样例输出
Data set 1: yes
Data set 2: yes
Data set 3: no

题目大意

给你三个字符串,让你用前两个字符串组成第三个字符串,前两个字符串的长度和等于第三个字符串长度,前两个字符串可以随便拆,但是不能改变字符在字符串里的顺序。输入输出见样例。

法一DFS(好理解一些)

从头到尾,用a,b,c做下标遍历搜索三个字符串,如果s1[a]==s3[c],a++,c++如果s2[b]==s3[c],b++,c++。把遍历过的标记下来,避免大量的重复计算。

参考代码

#include <iostream>
#include <string.h>
using namespace std;
char s1[201],s2[201],s3[402];
int visited[201][201];//标记数组,下标分别表示第一个字符串和第二个字符串的长度
int flag=0;//表示是否能组合
int len3;//第三个字符串的长度
void dfs(int a,int b,int c);
int main()
{
    int n,num=1;
    cin>>n;
    while(n){
        cin>>s1>>s2>>s3;
        len3=strlen(s3);
        memset(visited,0,sizeof(visited));
        dfs(0,0,0);
        if(flag==1){
            flag=0;
            cout<<"Data set "<<num<<": yes"<<endl;
        }
        else{
            cout<<"Data set "<<num<<": no"<<endl;
        }
        num++;
        n--;
    }
    return 0;
}
void dfs(int a,int b,int c){
    if(flag==1){//避免组合成功,函数返回的重复计算
        return;
    }
    if(c==len3){
        flag=1;
        return;
    }
    if(visited[a][b]==0){//避免组合不成功,函数返回的重复计算
        visited[a][b]=1;
        if(s1[a]==s3[c])
            dfs(a+1,b,c+1);
        if(s2[b]==s3[c])
            dfs(a,b+1,c+1);
    }
}

法二DP

子问题:第一个字符串的前a个字母和第二个字符串前的b个字母能否组合成第三个字符串前a+b个字母。

赋初值:第三个字符串的首字母或前几个字母一定是,第一个字符串的首字母或前几个字母,或第二个字符串的首字母或前几个字母。

#include <iostream>
#include <string.h>
using namespace std;
char s1[201],s2[201],s3[402];
int dp[201][201];
int a,b,c;//字符串的长度
int main()
{
    int n,num=1;
    cin>>n;
    while(n){
        cin>>(s1+1)>>(s2+1)>>(s3+1);
        a=strlen(s1+1);
        b=strlen(s2+1);
        c=strlen(s3+1);
    memset(dp,0,sizeof(dp));
    //初始化边界
    for(int i=1;i<=a;i++){
        if(s1[i]==s3[i]){
            dp[i][0]=1;
        }
        else{
            break;
        }
    }
    for(int i=1;i<=b;i++){
        if(s2[i]==s3[i]){
            dp[0][i]=1;
        }
        else{
            break;
        }
    }

    for(int i=1;i<=a;i++){//因为此处要看第三个字符串前(i+j)-1个字母是否能被组合所以必须从1开始遍历
        for(int j=1;j<=b;j++){
            if(s1[i]==s3[i+j]&&dp[i-1][j])
                dp[i][j]=1;
            if(s2[j]==s3[i+j]&&dp[i][j-1])
                dp[i][j]=1;
        }
    }

    if(dp[a][b]){
        cout<<"Data set "<<num<<": yes"<<endl;
    }
    else{
        cout<<"Data set "<<num<<": no"<<endl;
    }

        num++;
        n--;
    }
    return 0;
}

参考自:

①:http://www.makaidong.com/%E5%8D%9A%E5%AE%A2%E5%9B%AD6/20151001/222588.html

②:http://www.cnblogs.com/yu-chao/archive/2012/02/26/2369052.html

时间: 2024-10-11 00:20:53

【DFS或DP】Zipper的相关文章

UvaLive6661 Equal Sum Sets dfs或dp

UvaLive6661 PDF题目 题意:让你用1~n中k个不同的数组成s,求有多少种组法. 题解: DFS或者DP或打表. 1.DFS 由于数据范围很小,直接dfs每种组法统计个数即可. 1 //#pragma comment(linker, "/STACK:102400000,102400000") 2 #include<cstdio> 3 #include<cmath> 4 #include<iostream> 5 #include<cs

UVALive 6257 Chemist&#39;s vows --一道题的三种解法(模拟,DFS,DP)

题意:给一个元素周期表的元素符号(114种),再给一个串,问这个串能否有这些元素符号组成(全为小写). 解法1:动态规划 定义:dp[i]表示到 i 这个字符为止,能否有元素周期表里的符号构成. 则有转移方程:dp[i] = (dp[i-1]&&f(i-1,1)) || (dp[i-2]&&f(i-2,2))     f(i,k):表示从i开始填入k个字符,这k个字符在不在元素周期表中.  dp[0] = 1 代码: //109ms 0KB #include <ios

poj2378(dfs,树形dp)

和poj3107,poj1655一样的方法 #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<map> #include<set> #include<vector> #include<algorithm> #include<stack> #inc

poj1655(dfs,树形dp)

方法:就记节点1为树的根,两次dfs,第一次求出每个节点的所有子孙再加上它自己的节点总数num[i].第二次就算出每个节点的balance值bal[i],算的时候就比较节点i它所有子节点的num值(删掉它之后以每个它的子节点为根形成一棵新树)还有n-num[i]的值(删掉i之后它的父节点及其相关节点也形成一棵新树),最大的就是bal[i]. 注意:WA了几次是因为没有考虑边界情况(n==2),dfs写的太不熟练了,代码能力有待提高啊! #include<iostream> #include&l

poj1088 滑雪(dfs、dp优化)

#include <iostream> #include <map> #include <string> #include <cstdio> #include <sstream> #include <cstring> #include <vector> #include <cmath> #define N 110 int a,b,step=0; int anw=0; int moun[N][N]; int dp

dfs与dp算法之关系与经典入门例题

目录 声明 dfs与dp的关系 经典例题-数字三角形 - POJ 1163 题目 dfs思路 解题思路 具体代码 dp思路 解题思路 具体代码 声明 本文不介绍dfs.dp算法的基础思路,有想了解的可以自己找资源学习. 本文适合于刚刚接触dfs和dp算法的人,发现两种算法间的内在联系. 本人算法之路走之甚短,如果理解出现问题欢迎大家的指正,我会分享基于我目前理解到的算法思想. dfs与dp的关系 很多情况下,dfs和dp两种解题方法的思路都是很相似的,这两种算法在一定程度上是可以互相转化的. 想

Palindrome Partitioning[leetcode] DFS以及DP的解法

第一种方法是DFS,将所有可能的前缀找到,递归调用partition(剩余字符串) 复杂度为O(2^n) 代码如下: vector<vector<string>> partition(string s) { vector<vector<string>> res; vector<string> patition; if (s.size() == 0) return res; partition(s, patition, res); return r

zoj3816(dfs + 数位DP)

题意: 给出一个数n,从比n小的数中选出一个最大的; 满足压缩完是回文数,压缩指连续的相同数字,只算一个; 如1221就算做121; 1121算作121; 思路: 我们就是要从左边开始构造一个数; 首先我们在第一位放了一个数字;那么我们就要在最后一位放一个数字,为了让他们对称; 但是有几种情况,只需在左边放一个,而不需要在右边放; 就是出现重复数字的时候还有只剩一个位置的时候; 如果我们在最左边放了一个1,那么就要在最右边也放一个,然后我们再放一个1,就不需要在右边放了,因为左边两个1只算作1个

Divideing Jewels【dfs或DP】

Divideing Jewels Time Limit: 1 Sec Memory Limit: 128 MB Submit: 164 Solved: 22 [Submit][Status][Web Board] Description Mary and Rose own a collection of jewells. They want to split the collection among themselves so that both receive an equal share o