zoukankan      html  css  js  c++  java
  • 后缀数组应用

           求两个后缀数组的最长公共前缀,可以转化为求某个区间上的最小值。 接下来,先来构造后缀数组,先看这里    

    //求两个后缀的最长公共前缀 <1>
    int lcs(int i, int j){
      int b, e;
      if(RANK[i] > RANK[j])
        e=RANK[i], b=RANK[j]+1;
      else e=RANK[j], b=RANK[i]+1;
      int lcs=height[b++];
      for(; b<=e; ++b) lcs=min(lcs, height[b]);
      return lcs;
    }

           如果用RMQ 的  Sparse-Tree 预处理,则可以做到 O(nlogn)。

    // RMQ Sparse-Tree 预处理
    int m=log(len)/log(2.0)+1;	// len是字符串的长度
    int dp_min[maxlen][m], dp_max[maxlen][m];
    void RMQ_init(){
      int i=0,j=0;
      for(i=1; i<=len; i++)
        dp_max[i][0]=dp_min[i][0]=s[i];
      double k=log(n)/log(2.0);
      for(i=1; i<(int)k; i++)
        for(j=1; j+(1<<i)-1 <= n; i++){
          dp_max[j][i] = max(dp_max[i][j-1], dp_max[ j+(1<<(i-1)) ][i-1]);
          dp_min[j][i] = min(dp_min[i][j-1], dp_min[ j+(1<<(i-1)) ][i-1]);
        }
    }
    // RMQ :求两个后缀的最长公共前缀
    int RMQ_min(int i, int j){
      if(i>j)swap(i,j);
      int k=int(log(j-i)/log(2.0));
      return min(dp_min[i][k], dp_min[ j-(1<<k)+1 ][k]);
    }
            求可重叠最长重复子串,等价于求两个后缀的最长公共前缀的最大值,因为任意两个后缀的最长公共前缀都是height数组里的某一段的最小值,那么这个值一定不大于height数组里的最大值,所以,最长公共前缀就是height数组里的最大值了。上面已经用RMQ预处理了,那就利用起来把。

    // RMQ: 求可重叠最长重复子串
    int RMQ_max(int i, int j){
      if(i>j) swap(i,j);
      int k=int(log(j-i)/log(2.0));
      return max(dp_maxp[i][k], dp_max[ j-(1<<k)+1 ][k]);
    }
    
            求两个字符串的最长公共子串,先将第二个字符串写在第一个字符串后面,中间用一个没有出现过的字符隔开,再求这个新的字符串的后缀数组,在height[i]是两个字符串的公共前缀的前提下,求出height[i]的最大值。

    // 最长公共子串
    int longest_common_substring(int inter){
      // inter是两串字符串中间的分隔符的位置
      int ans = 0;
      for(int i = 2; i <= len; ++i)
        if((sa[i-1] < inter && sa[i] > inter) ||
           (sa[i] > inter && sa[i-1] > inter))
          ans = max(ans, height[i]);
      // if 判断部分看到别人是这样写的
      // if((sa[i-1] - inter)*(sa[i] - inter) < 0)
      return ans;
    }

         参考:罗穗骞 《后缀数组——处理字符串的有力工具》

          



    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    大牛都是这样写测试用例的,你get到了嘛?
    炸!分享美团面试关于selenium的面试题
    功能测试如何快速转向自动化测试?
    接口测试之深入理解HTTPS
    Linux之用户和权限
    Hash函数及其应用
    用代码控制网络断开与重连
    Windows Azure初体验
    JS跨域知识整理
    最大子序列和问题
  • 原文地址:https://www.cnblogs.com/Rex7/p/4752564.html
Copyright © 2011-2022 走看看