zoukankan      html  css  js  c++  java
  • HDU 5558 后缀数组+二分

    题意有一些绕,但其实就是对于不断变化的i,求以j(0=j<i)使得suffix[j]与suffix[i]的最长公共前缀最长,如果有多个j,则取最小的j。

    可以在rank数组中二分,在1-rank[i-1]中二分最接近i的j使得sa[j]小于i,通俗地说就是rank比的rank[i]小,并且位于i之前的后缀。因为这个是左边最接近rank[i]的,所以与suffix[i]的最长公共前缀一定是满足最大的。接下来再根据得到的LCP值,二分一个最小的j。同理,再从rank[i+1]到rank[n]中作类似二分。两者结合得到当前的K和T。

    其实这道题中间过程也可以不用二分,直接向左右暴力扫。速度会快很多。

      1 #include <iostream>
      2 #include <vector>
      3 #include <algorithm>
      4 #include <string>
      5 #include <string.h>
      6 #include <stdio.h>
      7 #include <queue>
      8 #include <stack>
      9 #include <map>
     10 #include <set>
     11 #include <cmath>
     12 #include <ctime>
     13 #include <cassert>
     14 #include <sstream>
     15 using namespace std;
     16 
     17 const int N=1e5+10;
     18 
     19 
     20 int MIN(int a,int b) {
     21     return a<b?a:b;
     22 }
     23 int MAX(int a,int b) {
     24     return a>b?a:b;
     25 }
     26 
     27 int val[N];
     28 struct RMQ {
     29     int dp[N][22];
     30     int (*cmp) (int,int);
     31     void setMin() {
     32         cmp=MIN;
     33     }
     34     void setMax() {
     35         cmp=MAX;
     36     }
     37     void init(int n,int *val) {
     38         for (int i=0; i<=n; i++)
     39             dp[i][0]=val[i];
     40         for (int j=1; (1<<j)<=n; j++) {
     41             int k=1<<(j-1);
     42             for (int i=0; i+k<=n; i++)
     43                 dp[i][j]=cmp(dp[i][j-1],dp[i+k][j-1]);
     44         }
     45     }
     46     int query(int a,int b) {
     47         if (a>b) swap(a,b);
     48         int dis=b-a+1;
     49         int k=log((double)dis)/log(2.0);
     50         return cmp(dp[a][k],dp[b-(1<<k)+1][k]);
     51     }
     52 } rmq;
     53 
     54 char s[N];
     55 struct SuffixArray {
     56     int wa[N], wb[N], cnt[N], wv[N];
     57     int rk[N], height[N];
     58     int sa[N];
     59     bool cmp(int r[], int a, int b, int l) {
     60         return r[a] == r[b] && r[a+l] == r[b+l];
     61     }
     62     void calcSA(char r[], int n, int m) {
     63         int i, j, p, *x = wa, *y = wb;
     64         for (i = 0; i < m; ++i) cnt[i] = 0;
     65         for (i = 0; i < n; ++i) cnt[x[i]=r[i]]++;
     66         for (i = 1; i < m; ++i) cnt[i] += cnt[i-1];
     67         for (i = n-1; i >= 0; --i) sa[--cnt[x[i]]] = i;
     68         for (j = 1, p = 1; p < n; j *= 2, m = p) {
     69             for (p = 0, i = n - j; i < n; ++i) y[p++] = i;
     70             for (i = 0; i < n; ++i) if (sa[i] >= j) y[p++] = sa[i] - j;
     71             for (i = 0; i < n; ++i) wv[i] = x[y[i]];
     72             for (i = 0; i < m; ++i) cnt[i] = 0;
     73             for (i = 0; i < n; ++i) cnt[wv[i]]++;
     74             for (i = 1; i < m; ++i) cnt[i] += cnt[i-1];
     75             for (i = n-1; i >= 0; --i) sa[--cnt[wv[i]]] = y[i];
     76             for (swap(x, y), p = 1, x[sa[0]] = 0, i = 1; i < n; ++i)
     77                 x[sa[i]] = cmp(y, sa[i-1], sa[i], j) ? p-1 : p++;
     78         }
     79     }
     80     void calcHeight(char r[], int n) {
     81         int i, j, k = 0;
     82         for (i = 1; i <= n; ++i) rk[sa[i]] = i;
     83         for (i = 0; i < n; height[rk[i++]] = k)
     84             for (k?k--:0, j = sa[rk[i]-1]; r[i+k] == r[j+k]; k++);
     85     }
     86     int lcp(int a,int b,int len) {
     87         if (a==b) return len-a;
     88         int ra=rk[a],rb=rk[b];
     89         if (ra>rb) swap(ra,rb);
     90         return queryST(ra+1,rb);
     91     }
     92     int st[N][22];
     93     int preLog2[N];
     94     void initST(int n) {
     95         for (int i=1; i<=n; i++)
     96             st[i][0]=height[i];
     97         for (int j=1; (1<<j)<=n; j++) {
     98             int k=1<<(j-1);
     99             for (int i=1; i+k<=n; i++)
    100                 st[i][j]=min(st[i][j-1],st[i+k][j-1]);
    101         }
    102         preLog2[1]=0;
    103         for(int i=2;i<=n;i++){
    104             preLog2[i]=preLog2[i-1]+((i&(i-1))==0);
    105         }
    106     }
    107     int queryST(int a,int b) {
    108         if (a>b) swap(a,b);
    109         int dis=b-a+1;
    110         int k=preLog2[dis];
    111         return min(st[a][k],st[b-(1<<k)+1][k]);
    112     }
    113     void solve(int n) {
    114         calcSA(s,n+1,128);
    115         calcHeight(s,n);
    116         initST(n);
    117         rmq.setMin();
    118         rmq.init(n,sa);
    119         printf("-1 %d
    ",s[0]);
    120         int i=1;
    121         while (i<n) {
    122             int l=1,r=rk[i]-1;
    123             int k=-1,t=s[i];
    124             int minIndex=-1;
    125             while (l<=r) {
    126                 int mid=(l+r)>>1;
    127                 int minSA=rmq.query(mid,rk[i]-1);
    128                 if (minSA<i)
    129                     l=mid+1,minIndex=minSA;
    130                 else
    131                     r=mid-1;
    132             }
    133             if (minIndex!=-1) {
    134                 int u=lcp(minIndex,i,n);
    135                 if (u) {
    136                     k=u;
    137                     int l=1,r=rk[i]-1,ret=-1;
    138                     while (l<=r) {
    139                         int mid=(l+r)>>1;
    140                         int curLCP=lcp(sa[mid],i,n);
    141                         if (curLCP>=u)
    142                             r=mid-1,ret=mid;
    143                         else l=mid+1;
    144                     }
    145                     t=rmq.query(ret,rk[i]-1);
    146                 }
    147             }
    148             l=rk[i]+1;
    149             r=n;
    150             minIndex=-1;
    151             while (l<=r) {
    152                 int mid=(l+r)>>1;
    153                 int minSA=rmq.query(rk[i]+1,mid);
    154                 if (minSA<i)
    155                     r=mid-1,minIndex=minSA;
    156                 else
    157                     l=mid+1;
    158             }
    159             if (minIndex!=-1) {
    160                 int u=lcp(minIndex,i,n);
    161                 if (u&&u>=k) {
    162                     if (u==k)
    163                         t=min(t,minIndex);
    164                     else
    165                         t=minIndex;
    166                     k=u;
    167                     int l=rk[i]+1,r=n,ret=-1;
    168                     while (l<=r) {
    169                         int mid=(l+r)>>1;
    170                         int curLCP=lcp(sa[mid],i,n);
    171                         if (curLCP>=u)
    172                             l=mid+1,ret=mid;
    173                         else r=mid-1;
    174                     }
    175                     t=min(t,rmq.query(rk[i]+1,ret));
    176                 }
    177             }
    178             if (k==-1) {
    179                 printf("-1 %d
    ",s[i]);
    180                 i++;
    181             } else {
    182                 printf("%d %d
    ",k,t);
    183                 i+=k;
    184             }
    185         }
    186     }
    187 } suf;
    188 
    189 int main () {
    190     int T;
    191     scanf("%d",&T);
    192     while (T--) {
    193         scanf("%s",s);
    194         int n=strlen(s);
    195         static int cas=1;
    196         printf("Case #%d:
    ",cas++);
    197         suf.solve(n);
    198     }
    199     return 0;
    200 }
  • 相关阅读:
    Servlet核心技术(上)
    Bootstrap详解
    ECMAScript6详解
    JQuery详解
    CSS详解
    HTML
    网站加载页面(HTML+CSS+JS,简易版)
    java中sort()方法的用法
    Maven常见jar包依赖
    解决idea的项目启动报404的问题
  • 原文地址:https://www.cnblogs.com/micrari/p/4993279.html
Copyright © 2011-2022 走看看