LCS最长公共子串(复习复习)- -

Posted 指尖泛出的繁华

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LCS最长公共子串(复习复习)- -相关的知识,希望对你有一定的参考价值。

 

详细解析LCS:传送通道

重点:

  

动态规划算法分以下4个步骤:

  1. 描述最优解的结构
  2. 递归定义最优解的值
  3. 按自底向上的方式计算最优解的值   //此3步构成动态规划解的基础。
  4. 由计算出的结果构造一个最优解。   //此步如果只要求计算最优解的值时,可省略

解决LCS问题,你要求三个方面的东西:1、LCS(Xm-1,Yn-1)+1;2、LCS(Xm-1,Y),LCS(X,Yn-1);3、max{LCS(Xm-1,Y),LCS(X,Yn-1)}

 

show me the code:

 1 Procedure LCS_LENGTH(X,Y);
 2 begin
 3   m:=length[X];
 4   n:=length[Y];
 5   for i:=1 to m do c[i,0]:=0;
 6   for j:=1 to n do c[0,j]:=0;
 7   for i:=1 to m do
 8     for j:=1 to n do
 9       if x[i]=y[j] then
10         begin
11           c[i,j]:=c[i-1,j-1]+1;
12           b[i,j]:="";
13         end
14       else if c[i-1,j]≥c[i,j-1] then
15         begin
16           c[i,j]:=c[i-1,j];
17           b[i,j]:="";
18         end
19       else
20         begin
21           c[i,j]:=c[i,j-1];
22           b[i,j]:=""
23         end;
24   return(c,b);
25 end;

 

 

uva,10066

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstdio>
 4 
 5 using namespace std;
 6 const int maxn=105;
 7 int lcs[maxn][maxn];
 8 int N1,N2;
 9 int main()
10 {
11     int s1[maxn],s2[maxn];
12     for(int t=1;;t++)
13     {
14         scanf("%d %d",&N1, &N2);
15         if(!N1 && !N2) break;
16         int i,j;
17         for(i = 0; i < N1; i++)
18             scanf("%d",&s1[i]);
19         for(j = 0; j < N2; j++)
20             scanf("%d",&s2[j]);
21         for(i=1;i<=N1;i++)
22             for(j=1;j<=N2;j++)
23             {
24                 if(s1[i-1]==s2[j-1])
25                     lcs[i][j]=lcs[i-1][j-1]+1;
26                 else
27                 {
28                     lcs[i][j]=max(lcs[i-1][j],lcs[i][j-1]);
29                 }
30             }
31         printf("Twin Towers #%d\n",t);
32         printf("Number of Tiles : %d\n\n",lcs[N1][N2]);
33     }
34     return 0;
35 }

 

UVA, 10192

 

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstdio>
 4 #include <cstdlib>
 5 #include <cstring>
 6 
 7 using namespace std;
 8 const int maxn=105;
 9 int lcs[maxn][maxn];
10 int m,n;
11 int main()
12 {
13     int t=1;
14     char s1[maxn],s2[maxn];
15     while(gets(s1))
16     {
17         if(s1[0]==#) break;
18         gets(s2);
19         m=strlen(s1);
20         n=strlen(s2);
21         for(int i=1;i<=m;i++)
22             for(int j=1;j<=n;j++)
23             {
24                 if(s1[i-1]==s2[j-1])
25                     lcs[i][j]=lcs[i-1][j-1]+1;
26                 else
27                 {
28                     lcs[i][j]=max(lcs[i-1][j],lcs[i][j-1]);
29                 }
30             }
31         printf("Case #%d: you can visit at most %d cities.\n",t++,lcs[m][n]);
32     }
33     return 0;
34 }

 

UVA, 531

两种回溯方式:自顶向下

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <string.h>
 4 #include <string>
 5 #include <cmath>
 6 using namespace std;
 7 
 8 int lcs[101][101];
 9 string s1[101],s2[101],seq[101];
10 int n1,n2;
11 int main()
12 {
13     int t,i,j;
14     string s;
15     while( cin >>s)
16     {
17         n1=n2=0;
18         while( 1)
19         {
20             if( s!="#")
21                 s1[++n1] =s;
22             else
23                 break;
24             cin >>s;
25         }
26         while( 1)
27         {
28             cin >>s;
29             if( s!="#")
30                 s2[++n2] =s;
31             else
32                 break;
33         }
34         memset( lcs, 0,sizeof( lcs));
35         for( i=1; i<=n1; i++)
36             for( j=1; j<=n2; j++)
37             {
38                 if( s1[i] ==s2[j] )
39                     lcs[i][j] = lcs[i-1][j-1] +1;
40                 else
41                     lcs[i][j] =max( lcs[i-1][j], lcs[i][j-1]);
42             }
43         int ans =lcs[n1][n2];
44         t= ans;
45         while( lcs[n1][n2])
46         {
47             if( lcs[n1][n2] ==lcs[n1-1][n2]) n1--;
48             else if( lcs[n1][n2] ==lcs[n1][n2-1]) n2--;
49             else
50             {
51                 seq[--t] =s1[n1];
52                 n1--; n2--;
53             }
54         }
55         for( i=0; i<ans; i++)
56             if( !i)
57                 printf("%s",seq[i].c_str());
58             else
59                 printf(" %s",seq[i].c_str());
60         printf("\n");
61     }
62     return 0;
63 }

自底向上:

引用别人的java代码

 1 import java.util.Random;
 2 
 3 public class LCS{
 4     public static void main(String[] args){
 5 
 6         //设置字符串长度
 7         int substringLength1 = 20;
 8         int substringLength2 = 20;  //具体大小可自行设置
 9 
10         // 随机生成字符串
11         String x = GetRandomStrings(substringLength1);
12         String y = GetRandomStrings(substringLength2);
13 
14         Long startTime = System.nanoTime();
15         // 构造二维数组记录子问题x[i]和y[i]的LCS的长度
16         int[][] opt = new int[substringLength1 + 1][substringLength2 + 1];
17 
18         // 动态规划计算所有子问题
19         for (int i = substringLength1 - 1; i >= 0; i--){
20             for (int j = substringLength2 - 1; j >= 0; j--){
21                 if (x.charAt(i) == y.charAt(j))
22                     opt[i][j] = opt[i + 1][j + 1] + 1;                                 //参考上文我给的公式。
23                 else
24                     opt[i][j] = Math.max(opt[i + 1][j], opt[i][j + 1]);        //参考上文我给的公式。
25             }
26         }
27 
28         -------------------------------------------------------------------------------------
29 
30         理解上段,参考上文我给的公式:
31 
32         根据上述结论,可得到以下公式,
33 
34         如果我们记字符串Xi和Yj的LCS的长度为c[i,j],我们可以递归地求c[i,j]:
35 
36         -------------------------------------------------------------------------------------
37 
38         System.out.println("substring1:"+x);
39         System.out.println("substring2:"+y);
40         System.out.print("LCS:");
41 
42         int i = 0, j = 0;
43         while (i < substringLength1 && j < substringLength2){
44             if (x.charAt(i) == y.charAt(j)){
45                 System.out.print(x.charAt(i));
46                 i++;
47                 j++;
48             } else if (opt[i + 1][j] >= opt[i][j + 1])
49                 i++;
50             else
51                 j++;
52         }
53         Long endTime = System.nanoTime();
54         System.out.println(" Totle time is " + (endTime - startTime) + " ns");
55     }
56 
57     //取得定长随机字符串
58     public static String GetRandomStrings(int length){
59         StringBuffer buffer = new StringBuffer("abcdefghijklmnopqrstuvwxyz");
60         StringBuffer sb = new StringBuffer();
61         Random r = new Random();
62         int range = buffer.length();
63         for (int i = 0; i < length; i++){
64             sb.append(buffer.charAt(r.nextInt(range)));
65         }
66         return sb.toString();
67     }
68 }

 

 

UVA, 10100

 1 #include <stdio.h>
 2 #include <iostream>
 3 #include <cctype>
 4 #include <algorithm>
 5 #include <string>
 6 #include <string.h>
 7 #include <vector>
 8 
 9 using namespace std;
10 int lcs[1010][1010];
11 int main()
12 {
13     char s3[1005],s4[1005];
14     int k=1;
15     while(gets(s3))
16     {
17         gets(s4);
18         if(s3[0]==‘\0‘ || s4[0]==‘\0‘)
19         {
20             printf("%2d. Blank!\n",k++);
21             continue;
22         }
23         int m=strlen(s3);
24         int n=strlen(s4);
25         int i,j;
26         string s1[1005],s2[1005];  //放全局就wa
27         int count1=0;
28         bool flag=false;
29         for(i=0;i<m;i++)
30         {
31             char c=s3[i];
32             if(isalpha(c) || isdigit(c))
33             {
34                 if(!flag)
35                 {
36                     count1++;
37                     s1[count1]+=c;
38                     flag=true;
39                 }
40                 else
41                     s1[count1]+=c;
42             }
43             else
44                 flag=false;
45         }
46         flag=false;
47         int count2=0;
48         for(i=0;i<n;i++)
49         {
50             char c=s4[i];
51             if(isalpha(c) || isdigit(c))
52             {
53                 if(!flag)
54                 {
55                     count2++;
56                     s2[count2]+=c;
57                     flag=true;
58                 }
59                 else
60                     s2[count2]+=c;
61             }
62             else
63                 flag=false;
64         }
65         for(i=1;i<=count1;i++)
66             for(j=1;j<=count2;j++)
67             {
68                 if(s1[i]==s2[j])
69                     lcs[i][j]=lcs[i-1][j-1]+1;
70                 else
71                     lcs[i][j]=max(lcs[i-1][j],lcs[i][j-1]);
72             }
73             printf("%2d. Length of longest match: %d\n",k++,lcs[count1][count2]);
74     } 
75     return 0;
76 }

 

 

以上是关于LCS最长公共子串(复习复习)- -的主要内容,如果未能解决你的问题,请参考以下文章

最长公共子串和最长公共子序列(LCS问题)

最长公共子串和最长公共子序列(LCS问题)

最长公共子序列和最长公共子串

最长公共子序列(LCS)

[LCS] nwHJ65 查找两个字符串a,b中的最长公共子串(LCS+KMP+substr暴力)

[LCS] nwHJ65 查找两个字符串a,b中的最长公共子串(LCS+KMP+substr暴力)