zoukankan      html  css  js  c++  java
  • 标题清洗引发的算法(两个字符串的最长公共子串)

    前言

    在做声音标题清洗的时候,需要将专辑的标题和声音的标题对比,如果他们的最长公共字符串长度大于三,则清除声音中的最长公共字符串,否则不清除。

    解析

    1. 把声音标题的字符串,放入x轴,把专辑标题的字符串,放入y轴。如下图一
    图一
    1. 当x为1的时候,为 "平",那么对应的 y轴上的字符,如果相同的话设置为1。
      如下图二

    图二
    1. 当y为1的时候,为 "平", 那么对应的 x轴上的字符,如果相同的话设置为1。

    2. 当x为2的时候,为 "凡", 那么对应 y轴上的字符,如果相同的话,查看 x-1,y-1 对应的数字大小加1,标注后如下图三

    图三
    1. 当x为3的时候, 为 "的",那么对应y轴上的字符,如果相同的话,查看 x-1,y-1 对应的数字大小加1,标注后如下图四
    图四
    。。。。。

    依次往下走,直到x上没有字符串为止。
    这是一个比较经典的动态规划算法,能够了解他的状态转移方程为 dp[i][j]=dp[i][j] + 1 时间复杂度为 O(nm);

    具体代码如下

    
      /**
         * @Author ouyangkang
         * @Description 清除两个字符串的最长公共子串,如果长度小于3 不清除
         * @Date 10:45 2019-10-31
         * @param albumTitle
         * @param trackTitle
         * @return java.lang.String
         **/
        private static String cleanTrackTitleFromAlbumTitle(String albumTitle, String trackTitle){
    
            if (StringUtils.isBlank(albumTitle) || StringUtils.isBlank(trackTitle)){
                return trackTitle;
            }
            Map<String, Integer> map = getLongestCommonSubstring(albumTitle, trackTitle);
            Integer len = map.get("len");
            Integer start = map.get("start");
            if (len > 3){
                start += 1;
                return trackTitle.replace(trackTitle.substring(start - len,start), "");
            }else {
                return trackTitle;
            }
        }
    
     /**
         * @Author ouyangkang
         * @Description 获取两个字符串最长公共子串
         * @Date 16:01 2019-10-31
         * @param albumTitle
         * @param trackTitle
         * @return java.util.Map<java.lang.String,java.lang.Integer>
        **/
        private static Map<String, Integer> getLongestCommonSubstring(String albumTitle, String trackTitle){
            Map<String, Integer> map = new HashMap<>();
            // 最长公共子串大小
            int len = 0;
            // 子串坐标
            int start = 0;
            // 最长公共子串大小 为 dp[i][j] = dp[i-1][j-1] + 1;
            int[][] dp = new int[albumTitle.length()][trackTitle.length()];
            for (int i = 0; i < albumTitle.length(); i++){
                for (int j = 0; j< trackTitle.length();j++){
                    if (i==0 && albumTitle.charAt(0)== trackTitle.charAt(j)){
                        dp[0][j] = 1;
                        continue;
                    }
    
                    if (j==0 && albumTitle.charAt(i) == trackTitle.charAt(0)){
                        dp[i][0] = 1;
                        continue;
                    }
    
                    if(albumTitle.charAt(i) == trackTitle.charAt(j)){
                        dp[i][j] = dp[i-1][j-1] + 1;
                        if (dp[i][j] > len){
                            len = dp[i][j];
                            start = j;
                        }
                    }
                }
            }
            // 记录长度
            map.put("len",len);
            // 记录声音标题的坐标
            map.put("start",start);
            return map;
        }
    

    调用 cleanTrackTitleFromAlbumTitle方法,入参为 "平凡的世界", "平凡的时间01"。返回的字符串为 01

    总结

    能够在日常开发中,写一写算法,并应用到程序中,不是curd,也是比较有意思的一件事,清洗的过程是很复杂的,这只是其中一步清洗,其他的清洗涉及到一些正则表达式。一开始写了些能够实现功能的正则,但是在同事的提醒下,发现了很涉及到正则的回溯。emmmm.. 这就是另说了,下次博客补上。

  • 相关阅读:
    Problem D: GJJ的日常之暴富梦(水题)
    Problem I: GJJ的日常之玩游戏(GDC)
    扩展欧几里得,解线性同余方程 逆元 poj1845
    poj3696 欧拉函数引用
    同余
    欧拉函数,打表求欧拉函数poj3090
    洛谷p1072 gcd,质因数分解
    gcd,lcm
    约数 求反素数bzoj1053 bzoj1257
    poj2992 阶乘分解
  • 原文地址:https://www.cnblogs.com/Krloypower/p/11777486.html
Copyright © 2011-2022 走看看