我們考慮,一個子串必定是某個后綴的前綴。
排序相鄰的后綴他們的前綴一定最相似。
所以全部的一種子串必定是一些排序相鄰的后綴的公共前綴。
從l開始的子串,則從rank[l]開始看,兩側height保證大於子串長度,能延伸多長,則證明有多少個這種子串。
我們用ST表維護出height的最小值,然后通過最小值二分即可,邊界有些棘手。
然后我們就得到了一個height不小於子串長度的連續區間,這個區間是以原后綴的字典序排序的。
而同時,sa數組下標為排序,值為原串位置。
所以我們對這個區間在sa數組上做主席樹,求第k大,即為第k個子串出現的位置。
1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 #include <cmath> 5 using namespace std; 6 const int MAXN = 101000; 7 char str[MAXN]; 8 int len,q,T,m,uni[30]; 9 struct ktree 10 { 11 int n,cnt; 12 int root[MAXN]; 13 int ls[MAXN * 40],rs[MAXN * 40],s[MAXN * 40]; 14 //插入一個新的版本,參數分別為左右區間,最近的歷史版本,現在的版本,插入的值 15 //k值加一個引用可以完美的處理新子節點的序號分配問題。 16 //s數組記錄了對應序號子樹的元素個數 17 void insert(int l,int r,int pre,int &k,int v) 18 { 19 k = ++cnt; 20 s[k] = s[pre] + 1; 21 if (l == r) 22 return; 23 int mid = (l + r) >> 1; 24 //由於我們k值傳了引用參,所以這里可以直接將左右節點全部賦上值。 25 ls[k] = ls[pre]; 26 rs[k] = rs[pre]; 27 //根據情況來進行左右遞歸。 28 if (v <= mid) 29 insert(l,mid,ls[pre],ls[k],v); 30 else 31 insert(mid + 1,r,rs[pre],rs[k],v); 32 } 33 //查詢x,y兩個歷史版本的權值線段樹相減的得到新的線段樹中的第k大 34 //這里我們考慮一下,如果我們求區間[x,y]的第k大。那么顯然第x-1個版本相當於[1,x-1]的權值線段樹,那么我們用第y個版本的線段樹-第x-1個版本的線段樹,得到就相當於是[x,y]區間得到的權值線段樹,然后我們可以在這棵線段樹上進行開心的查詢。 35 int ask(int l,int r,int k,int x,int y) 36 { 37 if (l == r) 38 return l; 39 int mid = (l + r) >> 1; 40 if (s[ls[y]] - s[ls[x]] >= k) 41 return ask(l,mid,k,ls[x],ls[y]); 42 return ask(mid + 1,r,k - (s[ls[y]] - s[ls[x]]),rs[x],rs[y]); 43 } 44 void build(int _n,int *vec) 45 { 46 n = _n; 47 for (int i = 1; i <= n; i++) 48 insert(1,n,root[i - 1],root[i],vec[i]); 49 } 50 void clear() 51 { 52 for (int i = 1; i <= cnt; i++) 53 s[i] = ls[i] = rs[i] = 0; 54 for (int i = 0; i <= n; i++) 55 root[i] = 0; 56 n = 0; 57 cnt = 0; 58 } 59 } kt; 60 struct suffixvec 61 { 62 int c[MAXN],sa[MAXN],rnk[MAXN],height[MAXN],tp[MAXN]; 63 int m,len; 64 char str[MAXN]; 65 void build(int _len,char *s) 66 { 67 len = _len; 68 strcpy(str + 1,s + 1);//因為要從1開始 69 } 70 void clear() 71 { 72 for (int i = 1; i <= len; i++) 73 sa[i] = rnk[i] = height[i] = 0; 74 } 75 void qsort() 76 { 77 for (int i = 0; i <= m; i++) 78 c[i] = 0; 79 for (int i = 1; i <= len; i++) 80 c[rnk[i]]++; 81 for (int i = 1; i <= m; i++) 82 c[i] += c[i - 1]; 83 for (int i = len; i >= 1; i--) 84 sa[c[rnk[tp[i]]]--] = tp[i]; 85 } 86 void get_sa() 87 { 88 m = 200; 89 for (int i = 1; i <= len; i++) 90 { 91 rnk[i] = str[i]; 92 tp[i] = i; 93 } 94 qsort(); 95 for (int k = 1,p = 0; p < len; m = p,k <<= 1) 96 { 97 p = 0; 98 for (int i = 1; i <= k; i++) 99 tp[++p] = len - k + i; 100 for (int i = 1; i <= len; i++) 101 if (sa[i] > k) 102 tp[++p] = sa[i] - k; 103 qsort(); 104 swap(tp,rnk); 105 rnk[sa[1]] = p = 1; 106 for (int i = 2; i <= len; i++) 107 rnk[sa[i]] = (tp[sa[i - 1]] == tp[sa[i]] && tp[sa[i - 1] + k] == tp[sa[i] + k]) ? p : ++p; 108 } 109 } 110 int solve(int x,int y) 111 { 112 int res = 0; 113 while (str[x++] == str[y++]) 114 res++; 115 return res; 116 } 117 void get_height() 118 { 119 int cur = 0; 120 for (int i = 1; i <= len; i++) 121 { 122 if (cur != 0) 123 cur--; 124 height[rnk[i]] = cur = cur + solve(i + cur,sa[rnk[i] + 1] + cur); 125 } 126 } 127 } sf; 128 struct stable 129 { 130 int p[MAXN][30]; 131 int len; 132 void init(int _len,int *vec) 133 { 134 len = _len; 135 int tp = log2(len); 136 for (int i = 1; i <= len; i++) 137 p[i][0] = vec[i]; 138 for (int i = 1; i <= tp; i++) 139 for (int j = 1; j + uni[i] - 1 <= len; j++) 140 p[j][i] = min(p[j][i - 1],p[j + uni[i - 1]][i - 1]); 141 } 142 int querymin(int l,int r) 143 { 144 int tp = log2(r - l + 1); 145 return min(p[l][tp],p[r - uni[tp] + 1][tp]); 146 } 147 } st; 148 int tdl(int x,int lt) 149 { 150 int l = 1,r = x; 151 while (l < r) 152 { 153 int mid = l + r >> 1; 154 if (st.querymin(mid,x) >= lt) 155 r = mid; 156 else 157 l = mid + 1; 158 } 159 return l; 160 } 161 int tdr(int x,int lt) 162 { 163 int l = x,r = len; 164 while (l < r) 165 { 166 int mid = l + r + 1 >> 1; 167 if (st.querymin(x,mid) >= lt) 168 l = mid; 169 else 170 r = mid - 1; 171 } 172 return l; 173 } 174 175 int main() 176 { 177 uni[0] = 1; 178 for (int i = 1; i <= 25; i++) 179 uni[i] = uni[i - 1] << 1; 180 for(scanf("%d",&T); T != 0; T--) 181 { 182 scanf("%d%d",&len,&q); 183 scanf("%s",str + 1); 184 sf.clear(); 185 sf.build(len,str); 186 sf.get_sa(); 187 sf.get_height(); 188 st.init(sf.len,sf.height); 189 kt.clear(); 190 kt.build(len,sf.sa); 191 int l,r,k,tl,tr; 192 for (int i = 1; i <= q; i++) 193 { 194 scanf("%d%d%d",&l,&r,&k); 195 if (sf.height[sf.rnk[l] - 1] < r - l + 1) 196 tl = sf.rnk[l]; 197 else 198 tl = tdl(sf.rnk[l] - 1,r - l + 1); 199 if (sf.height[sf.rnk[l]] < r - l + 1) 200 tr = sf.rnk[l]; 201 else 202 tr = tdr(sf.rnk[l],r - l + 1) + 1; 203 if (k > kt.s[kt.root[tr]] - kt.s[kt.root[tl - 1]]) 204 printf("-1\n"); 205 else 206 printf("%d\n",kt.ask(1,len,k,kt.root[tl - 1],kt.root[tr])); 207 } 208 } 209 return 0; 210 }