这道题完全没有思路。唉,可悲
看了大牛的思路才发现,人才啊,都是人才啊
我拿过来学习下
这道题大致分为三个步骤
1 求最大公共子串(LCS),这个应该是比较简答的方法,主要是动态转移方程,这里设i,j是字符串a,b的下标,dp[i][j]表示a的0~i ,b的0~j的最大公共子串
动态转移方程分为两种情况:
(1)a[i]==b[j] dp[i][j]=dp[i-1][j-1]+1;
(2)a[i]!=[j] dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
2 用两个变量last1[i][j], last2[i][j]来分别保存字符j(a的序号为0,b的序号为1,.....z的序号为25)在字符串1-i中出现的最大标号,要是字符j没有出现,则last[i][j] = 0;
3 然后从两个字符串的长度len1和len2开始枚举a---z字符,比如开始 t1 = last1[len1][0], t2 = last2[len2][0]表示a在s1字符串1---len1的最大下标为t1, 在s2字符串1--len2的最大下标为t2,那么若dp[t1][t2] 的值为s1和s2的最大公共子序列长度len则表示这个字符符合,保存起来,否则枚举下一个字符b。若满足情况的话,在继续在t1-1 和 t2 - 1 符合最大公共子序列为len - 1的字符串保存,如此循环,知道到达最长公共子序列为0时结束。把保存的字符串放入set集合里面,让它按字典序排序。
1 #include <stdio.h> 2 #include <cstring> 3 #include <string> 4 #include <set> 5 using namespace std; 6 char a[100]; 7 char b[105]; 8 int dp[105][105]; 9 int len,len1,len2; 10 int last1[105][105]; 11 int last2[105][105]; 12 char res[105];//最后一个\0不要忘了啊 13 int tmp; 14 set<string> collection; 15 int max(int a,int b) 16 { 17 return a>b?a:b; 18 } 19 void lcs()//求最大字串 20 { 21 int i,j; 22 for(i=1;a[i]!='\0';i++) 23 { 24 for(j=1;b[j]!='\0';j++) 25 { 26 if(a[i]==b[j]) 27 { 28 dp[i][j]=dp[i-1][j-1]+1; 29 } 30 else 31 { 32 dp[i][j]=max(dp[i-1][j],dp[i][j-1]); 33 } 34 } 35 } 36 len1=i-1; 37 len2=j-1; 38 len=dp[i-1][j-1]; 39 } 40 41 void initlast() 42 { 43 for(int i=0;i<26;i++) 44 { 45 char ch=i+'a'; 46 for(int j=1;j<=len1;j++) 47 { 48 for(int k=j;k>=1;k--) 49 { 50 if(a[k]==ch) 51 { 52 last1[j][i]=k; 53 break; 54 } 55 } 56 } 57 } 58 59 60 for(int i=0;i<26;i++) 61 { 62 char ch=i+'a'; 63 for(int j=1;j<=len2;j++) 64 { 65 for(int k=j;k>=1;k--) 66 { 67 if(b[k]==ch) 68 { 69 last2[j][i]=k; 70 break; 71 } 72 } 73 } 74 } 75 } 76 77 78 void search(int firstlen,int secondlen,int currentlen) 79 { 80 if(currentlen<=0) 81 { 82 collection.insert(&res[1]); 83 return; 84 } 85 for(int i=0;i<26;i++) 86 { 87 int t1=last1[firstlen][i]; 88 int t2=last2[secondlen][i]; 89 if(dp[t1][t2]==currentlen) 90 { 91 res[currentlen]='a'+i; 92 search(t1-1,t2-1,currentlen-1); 93 } 94 95 } 96 } 97 int main() 98 { 99 scanf("%s",&a[1]); 100 scanf("%s",&b[1]); 101 lcs(); 102 initlast(); 103 res[len+1]='\0'; 104 search(len1,len2,len); 105 for(set<string>::iterator iter = collection.begin(); iter != collection.end(); iter++) 106 printf("%s\n", iter->c_str()); 107 return 0; 108 }
个人不太喜欢参数传递,所以能省就省了
稍微难点的题还是很有意思的