Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 329|回复: 0

[算法学习]LCS的java算法

[复制链接]
  • TA的每日心情
    开心
    2021-3-12 23:18
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2014-11-6 00:03:06 | 显示全部楼层 |阅读模式
    LCS(Longest Common Subsequence) 就是求两个字符串最长公共子串的问题。 比如:   String str1 = new String("adbccadebbca");
       String str2 = new String("edabccadece");
    str1与str2的公共子串就是bccade.     解法就是用一个矩阵来记录两个字符串中所有位置的两个字符之间的匹配情况,若是匹配则为1,否则为0。然后求出对角线最长的1序列,其对应的位置就是最长匹配子串的位置.     下面是字符串21232523311324和字符串312123223445的匹配矩阵,前者为X方向的,后者为Y方向的。不难找到,红色部分是最长的匹配子串。通过查找位置我们得到最长的匹配子串为:21232
    0 0 0 1 0 0 0 1 1 0 0 1 0 0 0
    0 1 0 0 0 0 0 0 0 1 1 0 0 0 0
    1 0 1 0 1 0 1 0 0 0 0 0 1 0 0
    0 1 0 0 0 0 0 0 0 1 1 0 0 0 0
    1 0 1 0 1 0 1 0 0 0 0 0 1 0 0
    0 0 0 1 0 0 0 1 1 0 0 1 0 0 0
    1 0 1 0 1 0 1 0 0 0 0 0 1 0 0
    1 0 1 0 1 0 1 0 0 0 0 0 1 0 0
    0 0 0 1 0 0 0 1 1 0 0 1 0 0 0
    0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
    0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
    0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
                                                                                                                                 
    但是在0和1的矩阵中找最长的1对角线序列又要花去一定的时间。通过改进矩阵的生成方式和设置标记变量,可以省去这部分时间。下面是新的矩阵生成方式:
      
      
             0 0 0 1 0 0 0 1 1 0 0 1 0 0 0
    0 1 0 0 0 0 0 0 0 2 1 0 0 0 0
    1 0 2 0 1 0 1 0 0 0 0 0 1 0 0
    0 2 0 0 0 0 0 0 0 1 1 0 0 0 0
    1 0 3 0 1 0 1 0 0 0 0 0 1 0 0
    0 0 0 4 0 0 0 2 1 0 0 1 0 0 0
    1 0 1 0 5 0 1 0 0 0 0 0 2 0 0
    1 0 1 0 1 0 1 0 0 0 0 0 1 0 0
    0 0 0 2 0 0 0 2 1 0 0 1 0 0 0
    0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
    0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
    0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

         当字符匹配的时候,我们并不是简单的给相应元素赋上1,而是赋上其左上角元素的值加一。我们用两个标记变量来标记矩阵中值最大的元素的位置,在矩阵生成的过程中来判断当前生成的元素的值是不是最大的,据此来改变标记变量的值,那么到矩阵完成的时候,最长匹配子串的位置和长度就已经出来了。  这样做速度比较快,但是花的空间太多。我们注意到在改进的矩阵生成方式当中,每生成一行,前面的那一行就已经没有用了。因此我们只需使用一维数组即可。最终的代码如下:
       
       
       
         
         
         public
          
         class
          LCString2
         ...
         {

        public static void getLCString(char[] str1, char[] str2)
        ...{
            int i,j;
            int len1,len2;
            len1 = str1.length;
            len2 = str2.length;
            int maxLen = len1 > len2?len1:len2;
            int[] max = new int[maxLen];
            int[] maxIndex = new int[maxLen];
            int[] c = new int[maxLen];
            
            for (i = 0; i < len2 ; i++)
            ...{
                for (j = len1 -1; j >= 0; j--)
                ...{
                    if (str2 == str1[j])
                    ...{
                        if ( ( i == 0) || (j == 0) )
                            c[j] = 1;
                        else
                            c[j] = c[j-1] + 1;
                    }
                    else
                    ...{
                        c[j] = 0;
                    }
                   
                    if (c[j] > max[0])
                    ...{   //如果是大于那暂时只有一个是最长的,而且要把后面的清0;
                        max[0] = c[j];
                        maxIndex[0] = j;
                        
                        for (int k = 1; k < maxLen; k++)
                        ...{
                            max[k] = 0;
                            maxIndex[k] = 0;
                        }
                    }
                    else if (c[j] == max[0])
                    ...{   //有多个是相同长度的子串
                        for (int k = 1; k < maxLen; k++)
                        ...{
                            if (max[k] == 0)
                            ...{
                                max[k] = c[j];
                                maxIndex[k] = j;
                                break;  //在后面加一个就要退出循环了
                            }
                   
                        }
                    }
                }
            }
            
            for (j = 0; j < maxLen; j++)
            ...{
                if (max[j] > 0)
                ...{
                    System.out.println("第" + (j + 1) + "个公共子串:");
                    for (i = maxIndex[j] - max[j] + 1; i <= maxIndex[j]; i++)
                        System.out.print(str1);
                    System.out.println(" ");
                }            
            }
        }

        public static void main(String[] args) ...{
            
            String str1 = new String("adbba1234");
            String str2 = new String("adbbf1234sa");
            getLCString(str1.toCharArray(),str2.toCharArray());
        }
    }
         

         
       
    运行结果: C:java>java LCString2
    第1个公共子串:
    adbb
    第2个公共子串:
    1234
      
       
         
         
          
          

            
          

            
          
         
       

      


    源码下载:http://file.javaxxz.com/2014/11/6/000306296.zip
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-2-25 11:17 , Processed in 0.414425 second(s), 46 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表