【DFS或DP】Zipper
阿新 • • 發佈:2017-08-18
字母 course tro esp number oss pla notice col
總時間限制:
- 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
【DFS或DP】Zipper