最大公共连续子序列
经典:题给出两个字符串(可能包含空格),找出其中最长的公共连续子串,输出其长度。
第一反应一定是动态规划,那么需要注意以下几点:
1. 如果其中一个为空串或者都为空串,结果为0
if(len1==0 || len2==0) return 0;
2. 输入中可能包含空格,空格也将作为一个字符进行比较
我经常用经典的输入输出流,cin遇到回车和空格均当作字符串的结束,因此,处理方式如下:
//包含头文件 #include <string.h> #include <cstdio> //将字符串定义为char数组 char s1[50],s2[50]; //输入时,采用cin.getline(str,maxinum) cin.getline(s1,50); cin.getline(s2,50);
3. 申请二维数组是,第一,采用vector容器实现,第二,采用动态申请空间实现,我用的第二种
int len1=strlen(s1); int len2=strlen(s2); int max=-1; if(len1==0 || len2==0) return 0; int **a = new int *[len1+1]; //先动态申请行 int i,j; for(i=0;i<=len1; ++i) { a[i] = new int [len2+1]; //在动态申请列;p[i]的类型是int* 即整型指针; }
4. 填充数组是关键,当其中一个为空串是,结果一定为0,因此,第一行和第一列,均为0
for(i=0;i<=len1;i++) { a[i][0]=0; //s1为空串 } for(j=0;j<=len2;j++) { a[0][j]=0; //s2为空串 }
5. 其余部分,根据一直部分进行填充,由于本题为连续字符串,因此,填充时,仅需根据左上角元素进行填充,并且,随时更新二维矩阵中的最大值
//填充其余数组 for(i=1;i<=len1;i++) { for(j=1;j<=len2;j++) { if(s1[i-1]==s2[j-1]) { a[i][j]=a[i-1][j-1]+1; }else{ a[i][j]=0; } if(a[i][j]>max) max=a[i][j]; } }
6. 最大值max即为最大公共子串长度。
1 #include <iostream> 2 #include <string.h> 3 #include <cstdio> 4 #include <vector> 5 using namespace std; 6 char s1[50],s2[50]; 7 int ML(char* s1,char* s2) 8 { 9 int len1=strlen(s1); 10 int len2=strlen(s2); 11 int max=-1; 12 if(len1==0 || len2==0) 13 return 0; 14 int **a = new int *[len1+1]; //先动态申请行 15 int i,j; 16 for(i=0;i<=len1; ++i) 17 { 18 a[i] = new int [len2+1]; //在动态申请列;p[i]的类型是int* 即整型指针; 19 } 20 21 for(i=0;i<=len1;i++) 22 { 23 a[i][0]=0; //s1为空串 24 } 25 for(j=0;j<=len2;j++) 26 { 27 a[0][j]=0; //s2为空串 28 } 29 //填充其余数组 30 for(i=1;i<=len1;i++) 31 { 32 for(j=1;j<=len2;j++) 33 { 34 if(s1[i-1]==s2[j-1]) 35 { 36 a[i][j]=a[i-1][j-1]+1; 37 }else{ 38 a[i][j]=0; 39 } 40 if(a[i][j]>max) 41 max=a[i][j]; 42 } 43 } 44 for(i=0;i<=len1;i++) 45 { 46 for(j=0;j<=len2;j++) 47 { 48 cout<<a[i][j]<<" "; 49 } 50 cout<<endl; 51 } 52 return max; 53 54 } 55 int main() 56 { 57 cin.getline(s1,50); 58 cin.getline(s2,50); 59 cout<<ML(s1,s2)<<endl; 60 return 0; 61 }