zoukankan      html  css  js  c++  java
  • 《算法》第六章部分程序 part 4

    ▶ 书中第六章部分程序,包括在加上自己补充的代码,利用后缀树查找最长重复子串、查找最大重复子串并输出其上下文(Key word in context,KWIC)、求两字符串的最长公共子串

    ● 利用后缀树查找最长重复子串

     1 package package01;
     2 
     3 import edu.princeton.cs.algs4.StdIn;
     4 import edu.princeton.cs.algs4.StdOut;
     5 import edu.princeton.cs.algs4.SuffixArrayX;
     6 
     7 public class class01
     8 {
     9     private class01() {}
    10 
    11     public static String lrs(String text)
    12     {
    13         int n = text.length();
    14         SuffixArrayX sa = new SuffixArrayX(text);
    15         String lrs = "";
    16         for (int i = 1; i < n; i++)                             // 遍历一次,记录最长公共前缀
    17         {
    18             int length = sa.lcp(i);
    19             if (length > lrs.length())
    20                 lrs = text.substring(sa.index(i), sa.index(i) + length);
    21         }
    22         return lrs;
    23     }
    24 
    25     public static void main(String[] args)
    26     {
    27         String text = StdIn.readAll().replaceAll("\s+", " ");  // 空白字符全部换成 ' '
    28         StdOut.println("'" + lrs(text) + "'");
    29     }
    30 }

    ● 利用后缀树查找最大重复子串并输出其上下文(Key word in context,KWIC)

     1 package package01;
     2 
     3 import edu.princeton.cs.algs4.In;
     4 import edu.princeton.cs.algs4.StdIn;
     5 import edu.princeton.cs.algs4.StdOut;
     6 import edu.princeton.cs.algs4.SuffixArrayX;
     7 
     8 public class class01
     9 {
    10     private class01() {}
    11 
    12     public static void main(String[] args)
    13     {
    14         In in = new In(args[0]);                                                    // 命令参数,分别为输入文件和需要输出的上下文字符数量
    15         int context = Integer.parseInt(args[1]);
    16         String text = in.readAll().replaceAll("\s+", " ");
    17         int n = text.length();
    18         SuffixArrayX sa = new SuffixArrayX(text);
    19 
    20         for (; StdIn.hasNextLine(); StdOut.println())
    21         {
    22             String query = StdIn.readLine();
    23             for (int i = sa.rank(query); i < n; i++)
    24             {
    25                 int from1 = sa.index(i), to1 = Math.min(n, from1 + query.length()); // 取 index[i] 的头和尾,要求它和 query 不同
    26                 if (!query.equals(text.substring(from1, to1)))
    27                     break;
    28                 int from2 = Math.max(0, sa.index(i) - context), to2 = Math.min(n, sa.index(i) + context + query.length());
    29                 StdOut.println(text.substring(from2, to2));                         // 向前向后各取 context 个字符
    30             }
    31         }
    32     }
    33 }

    ● 利用后缀树求两字符串的最长公共子串

     1 package package01;
     2 
     3 import edu.princeton.cs.algs4.In;
     4 import edu.princeton.cs.algs4.StdOut;
     5 import edu.princeton.cs.algs4.SuffixArrayX;
     6 
     7 public class class01
     8 {
     9     private class01() {}
    10 
    11     private static String lcp(String s, int p, String t, int q)     // 返回 s[p] 和 t[q] 开始的两个子串的最大公共子串
    12     {
    13         int n = Math.min(s.length() - p, t.length() - q);
    14         for (int i = 0; i < n; i++)                                 // 逐元素比较就好了,返回保持相等的最长子串
    15         {
    16             if (s.charAt(p + i) != t.charAt(q + i))
    17                 return s.substring(p, p + i);
    18         }
    19         return s.substring(p, p + n);
    20     }
    21 
    22     private static int compare(String s, int p, String t, int q)    // 比较两个后缀元素的字典序,用于判断哪个后缀元素要改用下一个
    23     {
    24         int n = Math.min(s.length() - p, t.length() - q);
    25         for (int i = 0; i < n; i++)
    26         {
    27             if (s.charAt(p + i) != t.charAt(q + i))
    28                 return s.charAt(p + i) - t.charAt(q + i);
    29         }
    30         if (s.length() - p < t.length() - q)
    31             return -1;
    32         else if (s.length() - p > t.length() - q)
    33             return +1;
    34         return  0;
    35     }
    36 
    37     public static String lcs(String s, String t)
    38     {
    39         SuffixArrayX suffix1 = new SuffixArrayX(s), suffix2 = new SuffixArrayX(t);
    40         String lcs = "";
    41         for (int i = 0, j = 0; i < s.length() && j < t.length();)   // 两个后缀数组比较 O(s.length() + t.length()) 次
    42         {                                                           // 每次检查两个后缀元素的最长相等子串
    43             int p = suffix1.index(i), q = suffix2.index(j);         // 一旦找到不相等的元素,字典序靠前的元素就取下一个后缀元素继续比较
    44             String x = lcp(s, p, t, q);
    45             if (x.length() > lcs.length())
    46                 lcs = x;
    47             if (compare(s, p, t, q) < 0)
    48                 i++;
    49             else
    50                 j++;
    51         }
    52         return lcs;
    53     }
    54 
    55     public static void main(String[] args)
    56     {
    57         In in1 = new In(args[0]), in2 = new In(args[1]);
    58         String s = in1.readAll().trim().replaceAll("\s+", " ");
    59         String t = in2.readAll().trim().replaceAll("\s+", " ");
    60         StdOut.println("'" + lcs(s, t) + "'");
    61     }
    62 }
  • 相关阅读:
    (转)正则表达式与Python(RE)模块
    (转)【面试】【MySQL常见问题总结】【03】
    (转)MySQL性能调优my.cnf详解
    (转)python logging模块
    (转)python collections模块详解
    mysql故障总结
    rocksdb 编译安装 日志
    c++11 gcc4.8.x安装
    Install ssdb-rocks on CentOS 6
    在Shell里面判断字符串是否为空
  • 原文地址:https://www.cnblogs.com/cuancuancuanhao/p/9945104.html
Copyright © 2011-2022 走看看