zoukankan      html  css  js  c++  java
  • HDU 6194 string string string ——(2017沈阳网络赛,后缀数组)

      思路见:http://blog.csdn.net/aozil_yang/article/details/77929216

      代码如下:

      1 #include <stdio.h>
      2 #include <algorithm>
      3 #include <string.h>
      4 using namespace std;
      5 const int N = 1e5 + 100;
      6 typedef long long ll;
      7 
      8 /**
      9  *    sa[i]:表示排在第i位的后缀的起始下标
     10  *    rank[i]:表示后缀suffix(i)排在第几
     11  *    height[i]:sa[i-1] 与 sa[i]的LCP(最长公共前缀)值
     12  *
     13  * */
     14  /*
     15     如果整数的话模板改成int.
     16     加一个数a[n] = 0 。 这样他的排名是第一个。
     17     construct(a,n+1);
     18 
     19     字符串的话。
     20     len = strlen(str);
     21     construct(s,strlen(s)+1);
     22     排名第0的是个空字符串。
     23 
     24     height[i]:sa[i-1] 与 sa[i]的LCP(最长公共前缀)值
     25     所以height[1] = 0;
     26     rank[len] = 0;
     27     sa[0] = len;
     28  */
     29 int sa[N],rnk[N],height[N];
     30 void construct(const char *s,int n,int m = 256) {
     31     static int t1[N],t2[N],c[N];
     32     int *x = t1,*y = t2;
     33     int i,j,k,p,l;
     34     for (i = 0; i < m; ++ i) c[i] = 0;
     35     for (i = 0; i < n; ++ i) c[x[i] = s[i]] ++;
     36     for (i = 1; i < m; ++ i) c[i] += c[i - 1];
     37     for (i = n - 1; i >= 0; -- i) sa[--c[x[i]]] = i;
     38     for (k = 1; k <= n; k <<= 1) {
     39         p = 0;
     40         for (i = n - k; i < n; ++ i) y[p++] = i;
     41         for (i = 0; i < n; ++ i) if (sa[i] >= k) y[p++] = sa[i] - k;
     42         for (i = 0; i < m; ++ i) c[i] = 0;
     43         for (i = 0; i < n; ++ i) c[x[y[i]]] ++;
     44         for (i = 1; i < m; ++ i) c[i] += c[i - 1];
     45         for (i = n - 1; i >= 0; -- i) sa[--c[x[y[i]]]] = y[i];
     46         std::swap(x,y);
     47         p = 1; x[sa[0]] = 0;
     48         for (i = 1; i < n; ++ i)
     49             x[sa[i]] = y[sa[i - 1]] == y[sa[i]]
     50                 && y[sa[i - 1] + k] == y[sa[i] + k] ? p - 1: p ++;
     51         if (p >= n) break;
     52         m = p;
     53     }
     54     for (i = 0; i < n; ++ i) rnk[sa[i]] = i;
     55     for (i = 0,l = 0; i < n; ++ i) {
     56         if (rnk[i]) {
     57             j = sa[rnk[i] - 1];
     58             while (s[i + l] == s[j + l]) l++;
     59             height[rnk[i]] = l;
     60             if (l) l--;
     61         }
     62     }
     63 }
     64 
     65 
     66 int st_min[N][32];
     67 int preLog[N];
     68 int n;
     69 void init_rmq()
     70 {
     71     preLog[1] = 0;
     72     for(int i=2;i<=n;i++)
     73     {
     74         preLog[i] = preLog[i-1];
     75         if((1 << preLog[i] + 1) == i) preLog[i]++;
     76     }
     77     for(int i=n;i>=1;i--)
     78     {
     79         st_min[i][0] = height[i];
     80         for(int j=1;(i+(1<<j)-1)<=n;j++)
     81         {
     82             st_min[i][j] = min(st_min[i][j-1], st_min[i+(1<<j-1)][j-1]);
     83         }
     84     }
     85 }
     86 int query_min(int l,int r)
     87 {
     88     int len = r - l + 1, k = preLog[len];
     89     return min(st_min[l][k], st_min[r-(1<<k)+1][k]);
     90 }
     91 char s[N];
     92 int lcp(int l, int r)
     93 {
     94     /*int ql = rnk[l], qr = rnk[r];
     95     if(ql > qr) swap(ql, qr);
     96     if(ql == qr) return n - l;
     97     return query_min(ql+1, qr);*/
     98     // l and r are number in rnk.
     99     if(l == r) return n - sa[l];
    100     return query_min(l+1, r);
    101 }
    102 
    103 int main()
    104 {
    105     int T; scanf("%d",&T);
    106     while(T--)
    107     {
    108         int k; scanf("%d",&k);
    109         scanf("%s",s);
    110         n = strlen(s);
    111         s[n] = 0;
    112         construct(s, n+1);
    113         init_rmq();
    114 
    115         ll ans = 0;
    116         for(int i=1;i+k-1<=n;i++)
    117         {
    118             ans += lcp(i, i+k-1);
    119             if(i-1 >= 1) ans -= lcp(i-1, i+k-1);
    120             if(i+k <= n) ans -= lcp(i, i+k);
    121             if(i-1 >= 1 && i+k <= n) ans += lcp(i-1, i+k);
    122         }
    123         printf("%I64d
    ",ans);
    124     }
    125     return 0;
    126 }

      

      最后仍然需要注意的是我sa的模板中,除了rnk数组其他都是0-base的。

     

  • 相关阅读:
    设计模式-观察者模式
    ps一寸照的编辑
    ps剪切蒙版的使用
    ps扣头发
    mysql索引优化
    ES6 $ ES5
    sping-mybatis集成
    多线程--volatile
    eclipse.exe打开是报错
    Spring Aop 详解二
  • 原文地址:https://www.cnblogs.com/zzyDS/p/7507030.html
Copyright © 2011-2022 走看看