当前位置:   article > 正文

字母(letter)_26u

26u

字母(letter)

【题目描述】

给定一个字符串。取出的所有子串,并按字典序从小到大排序,然后将这些排完序的字符串首尾相接,记为字符串。有次询问,每次询问中的第个字符。

是被加密的,每次询问给出两个正整数,设为之前所有询问答案的ASCII码之和。初始时为。则该次询问的。

 

【输入格式】

输入第一行包含一个字符串,第二行包含一个正整数。

接下来行,每行两个正整数P,M。

 

【输出格式】

输出行,分别表示每个询问的答案。

 

【输入样例】

caaacacbbbababba

6

3 101

16 101

21 41

22 129

33 131

40 100

 

【输出样例】

a

a

a

b

c

a

 

【数据范围与约定】

对于100%的数据,,中仅包含小写字母。

数据编号

0

1-2

3-4

5-9

 

这是一道后缀树的题目

因为后缀树的先序遍历是可以按顺序找出所有的子串的

所以后缀自动机反着跑,建后缀树,具体方式参见dalao博客

然后就可以考虑一个点的father和它的关系

father的right集合比当前点是要多的,而且right集合的代表的长度是一段连续的区间

所以考虑一个点的贡献,那么就是一段连续长度的子串

对于每个节点有一个pos记录它的最后一个点在哪里,以及length长度

而且一个点的父亲的所有节点的开头必定不会是同一个字符,否则就会合并到父亲

那么一个点的长度就在length[fa[x]]+1到length[x]之间,然后在二分这里面的长度

得到一个length后,用pos找出具体是哪个字符就可以了

代码自己不想写,而且很不熟练,借的是yyyuuu dalao的代码

  1. #include <cstdio>
  2. #include <algorithm>
  3. #include <cstring>
  4. using namespace std ;
  5. #define LL long long
  6. int fa[400005] , to[400005][26] , mx[400005] , cnt[400005] , pos[400005] , linker[400005][26] , lzw , las ;
  7. char s1[200005] , s2[200005] ;
  8. void insert ( int x , int id )
  9. {
  10. int np = ++lzw , nd = las ; las = lzw ; mx[np] = mx[nd] + 1 ; cnt[np] = 1 ; pos[np] = id ;
  11. while ( nd != -1 && !to[nd][x] ) to[nd][x] = np , nd = fa[nd] ;
  12. if ( nd == -1 ) { fa[np] = 0 ; return ; }
  13. int q = to[nd][x] ;
  14. if ( mx[q] == mx[nd] + 1 ) { fa[np] = q ; return ; }
  15. int nq = ++lzw ;
  16. fa[nq] = fa[q] , mx[nq] = mx[nd] + 1 ; for ( int i = 0 ; i < 26 ; i++ ) to[nq][i] = to[q][i] ;
  17. fa[q] = fa[np] = nq ; pos[nq] = pos[q] ;
  18. while ( nd != -1 && to[nd][x] == q ) to[nd][x] = nq , nd = fa[nd] ;
  19. }
  20. bool cmp ( const int &a , const int &b ) { return mx[a] < mx[b] ; }
  21. LL s[400005] ; int hf , que[400005] ;
  22. void dfs ( int u )
  23. {
  24. if ( u ) s[++hf] = 1ll * ( mx[u] + mx[fa[u]] + 1 ) * ( mx[u] - mx[fa[u]] ) / 2 * cnt[u] , que[hf] = u ;
  25. for ( int i = 0 ; i < 26 ; i++ )
  26. if ( linker[u][i] ) dfs ( linker[u][i] ) ;
  27. }
  28. void init ( )
  29. {
  30. dfs ( 0 ) ;
  31. for ( int i = 1 ; i <= hf ; i++ ) s[i] += s[i-1] ;
  32. }
  33. LL K ; int Q ;
  34. char query ( )
  35. {
  36. int l = 0 , r = lzw , pps ;
  37. while ( l <= r )
  38. {
  39. int mid = l + r >> 1 ;
  40. if ( s[mid] < K ) pps = mid , l = mid + 1 ;
  41. else r = mid - 1 ;
  42. }
  43. K -= s[pps] ; int u = que[pps + 1] ;
  44. l = mx[fa[u]] , r = mx[u] ;
  45. while ( l <= r )
  46. {
  47. int mid = l + r >> 1 ;
  48. if ( 1ll * ( mid + mx[fa[u]] + 1 ) * ( mid - mx[fa[u]] ) / 2 * cnt[u] < K ) pps = mid , l = mid + 1 ;
  49. else r = mid - 1 ;
  50. }
  51. K -= 1ll * ( pps + mx[fa[u]] + 1 ) * ( pps - mx[fa[u]] ) / 2 * cnt[u] ;
  52. K = ( K - 1 ) % ( pps + 1 ) + 1 ;
  53. return s2[pos[u] - K + 1] ;
  54. }
  55. int main ( )
  56. {
  57. fa[0] = -1 ;
  58. scanf ( "%s" , s1 + 1 ) ; int havedinner = strlen ( s1 + 1 ) ; for ( int i = 1 ; i <= havedinner ; i++ ) s2[i] = s1[havedinner - i + 1] ;
  59. for ( int i = 1 ; i <= havedinner ; i++ ) insert ( s2[i] - 'a' , i ) ;
  60. for ( int i = 1 ; i <= lzw ; i++ ) que[i] = i ;
  61. sort ( que + 1 , que + lzw + 1 , cmp ) ;
  62. for ( int i = lzw ; i >= 1 ; i-- ) cnt[fa[que[i]]] += cnt[que[i]] ;
  63. for ( int i = 1 ; i <= lzw ; i++ ) linker[fa[i]][s2[pos[i] - mx[fa[i]]] - 'a'] = i ;
  64. init ( ) ;
  65. scanf ( "%d" , &Q ) ;
  66. int tota = 0 ;
  67. while ( Q-- )
  68. {
  69. int p ; LL m ;
  70. scanf ( "%d%lld" , &p , &m ) ;
  71. K = 1ll * p * tota % m ; K++ ;
  72. char g = query ( ) ;
  73. tota += g ;
  74. printf ( "%c\n" , g ) ;
  75. }
  76. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/208567
推荐阅读
相关标签
  

闽ICP备14008679号