We consider a sub-string must be a prefix of a suffix.
Sort adjacent to their suffix prefix certainly the most similar.
So all of a substring must be some sort of common prefix neighboring suffix.
L substring from the beginning, from Rank [l] start to see both sides of the height is greater than the length of the substring guaranteed, can extend long, it is proved that the number of such sub-strings.
We maintain a minimum height ST table, and then by half to a minimum, some thorny border.
Then we get a height not less than the length of the substring successive interval is the interval of the original lexicographical ordering suffix.
While, sa array labeled sorting, the original value of the string position.
So we did this interval on the sa array Chairman tree, find the first large k, k is the position of the first substring that appears.
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 // insert a new version, the parameters are about range, the most recent version of history, the current version, insert the value 15 // number k value plus the distribution of a reference can perfectly handle the new child node. 16 // S array record number corresponding to the number of elements in the subtree . 17 void INSERT ( int L, int R & lt, int pre, int & K, int V) 18 is { . 19 K = ++ CNT; 20 is S [K] S = [pre] + . 1 ; 21 is IF (L == R & lt) 22 is return ; 23 is int MID = (L + R & lt) >> . 1 ; 24 // As we pass a reference to the reference value of k, so here you can directly assign the value of all the nodes around. 25 LS [K] = LS [pre]; 26 is RS [K] = RS [pre]; 27 // performed recursively according to the situation around. 28 IF (V <= MID) 29 INSERT (L, MID, LS [pre], LS [K], V); 30 the else 31 is INSERT (MID + . 1 , R & lt, RS [pre], RS [K], V ); 32 } 33 // query x, y two revisions weights segment tree subtraction obtained new segment tree is k-th largest 34 // here we consider, if we find the interval [x, y] the k-th largest. Then obviously the first x-1 version is equivalent to [1, x-1] weights tree line, then we use the first version of the tree line y - x-1 the first version of the tree line, to get the equivalent of [x , y] section to get weights tree line, then we can be happy query tree line tree. 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 , flax, k, kt.root [TL - 1 ] kt.root [tr])); 207 } 208 } 209 return 0 ; 210 }