最长公共子序列与最长公共字串

Posted thewinter

tags:

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

显然最长公共子序列不一定需要连续的,只要字符的顺序严格递增即可。最长公共字串需要字符连续

子序列代码:

package test;

import java.util.*;
/*
 * 本题是求最长公共子序列,子序列未必连续,只需要严格递增即可
 * 如  abcdeeeeeeeee和atttbggcd 最长公共子序列为abcd 长度为4
 * 
 * */
public class Main4
    public static void main(String... args)
        try(Scanner in = new Scanner(System.in))
            while(in.hasNext())
            
                String s1 = in.nextLine();
                String s2 = in.nextLine();
                String min1 = s1.length() < s2.length()? s1 : s2;
                String max1 = s1.equals(min1) ? s2 : s1;
                 //dp[i][j]表示i串和j串的最长公共字串
                char[] min = min1.toCharArray();
                char[] max = max1.toCharArray();
                int[][] dp = new int[max.length+1][max.length+1]; 
                for(int i = 1; i < min.length + 1;i++) 
                    for(int j = 1; j < max.length + 1;j++) 
                        if(min[i-1] == max[j-1]) 
                            dp[i][j] = dp[i-1][j-1] + 1;
                        else 
                            dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]);
                            
                    
                
                
                for(int i = 0; i < min.length + 1; i++) 
                    for(int j = 0; j < max.length + 1;j++) 
                        if(j == max.length)
                            System.out.println(dp[i][j]);
                        else System.out.print(dp[i][j] + "  ");
                    
                
                System.out.println("++++++++++++++++++++");
                int flag = 0;
                for(int i = 0; i < min.length + 1;i++) 
                    for(int j = 0; j < max.length + 1; j++) 
                        if(dp[i][j] == flag + 1) 
                            System.out.print(max[j-1]);
                            flag = dp[i][j];
                        
                    
                
            
        
    

最长公共字串代码

package test;

import java.util.*;
public class Main2
    public static void main(String... args)
        try(Scanner in = new Scanner(System.in))
            while(in.hasNext())
            
                String s1 = in.nextLine();
                String s2 = in.nextLine();
                String min1 = s1.length() < s2.length()? s1 : s2;
                String max1 = s1.equals(min1) ? s2 : s1;
                 //dp[i][j]表示i串和j串的最长公共字串
                char[] min = min1.toCharArray();
                char[] max = max1.toCharArray();
                int[][] dp = new int[max.length+1][max.length+1]; 
                for(int i = 1; i < min.length + 1;i++) 
                    for(int j = 1; j < max.length + 1;j++) 
                        if(min[i-1] == max[j-1]) 
                            dp[i][j] = dp[i-1][j-1] + 1;
                        
                    
                
                
                for(int i = 0; i < min.length + 1; i++) 
                    for(int j = 0; j < max.length + 1;j++) 
                        if(j == max.length)
                            System.out.println(dp[i][j]);
                        else System.out.print(dp[i][j] + "  ");
                    
                
                System.out.println("++++++++++++++++++++");
                int flag = 0;
                int MAX = 0;
                int end = 0;
                
                for(int i = 1; i < min.length + 1;i++) 
                    for(int j = 1; j < max.length + 1; j++) 
                        if(dp[i][j] > MAX) 
                            MAX = dp[i][j];
                            end = j;
                        
                    
                
                System.out.println("MAX为:"+ MAX);
                System.out.println("end为:"+ end);
                for(int i = end - MAX ; i < end; i++) 
                    if(i == end - 1) System.out.println(max[i]);
                    else System.out.print(max[i]);
                
            
        
    

仔细比对两处代码可知,公共子序列需要将每一次循环中记录子序列的结果,dp的值一直更新(虽然值有可能不变)。而公共字串只有当字符连续的时候,dp值才会发生更新。

公共子序列在输出结果时,我们可以先把状态矩阵打印出来,观察矩阵可知,当每组数据第一次发生变化,就是子序列的值。比如

技术图片

当然,也可以纵向理解,则打印出min的第一次变化处的值即可。

以上是关于最长公共子序列与最长公共字串的主要内容,如果未能解决你的问题,请参考以下文章

最长递归子序列最长公共字串最长公共子序列编辑距离

子串子序列问题

两个字符串的所有公共最长子序列

最长公共子序列算法求破!杭电1159

C语言实现最长公共子串与最长公共子序列

动态规划——最长公共子序列与最长公共子串 (含Python实现代码)