题意有一些绕,但其实就是对于不断变化的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 }