Advertisement
Guest User

Untitled

a guest
Aug 28th, 2016
70
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.76 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. typedef long long ll;
  4. typedef unsigned long long ull;
  5. typedef long double ld;
  6. const int MAXN = 200 * 1000 + 7;
  7. const ll P1 = 37, Q1 = 1000 * 1000 * 1000 + 9, P2 = 41, Q2 = 1000 * 1000 * 1000 + 7;
  8. const ll A = 100 * 1000 + 1, B = 1000 * 1000 * 1000 + 7;
  9. ll ppows1[MAXN];
  10. ull ppows2[MAXN];
  11. ll apows[MAXN];
  12. struct ResultHash
  13. {
  14. ll value;
  15. int len;
  16. ResultHash()
  17. {
  18. value = 0;
  19. len = 0;
  20. }
  21. ResultHash(char c)
  22. {
  23. value = (int)c;
  24. len = 1;
  25. }
  26. };
  27. ResultHash merge(ResultHash l, ResultHash r)
  28. {
  29. ResultHash res;
  30. res.len = l.len + r.len;
  31. res.value = (l.value * apows[r.len] + r.value) % B;
  32. return res;
  33. }
  34. struct SegmentTree
  35. {
  36. vector<ResultHash> tree;
  37. SegmentTree(int n)
  38. {
  39. tree.resize(4 * n + 7);
  40. }
  41. void build(string& s, int v, int tl, int tr)
  42. {
  43. if (tl == tr)
  44. {
  45. tree[v] = ResultHash(s[tl - 1]);
  46. }
  47. else
  48. {
  49. int tm = (tl + tr) / 2;
  50. build(s, 2 * v, tl, tm);
  51. build(s, 2 * v + 1, tm + 1, tr);
  52. tree[v] = merge(tree[2 * v], tree[2 * v + 1]);
  53. }
  54. }
  55. ResultHash get(int v, int tl, int tr, int l, int r)
  56. {
  57. if (r < tl || l > tr) return ResultHash();
  58. if (tl >= l && tr <= r) return tree[v];
  59. int tm = (tl + tr) / 2;
  60. return merge(get(2 * v, tl, tm, l, r), get(2 * v + 1, tm + 1, tr, l, r));
  61. }
  62. };
  63. struct Hash
  64. {
  65. ll value1;
  66. ull value2;
  67. int deg;
  68. Hash()
  69. {
  70. value1 = 0;
  71. value2 = 0;
  72. deg = 0;
  73. }
  74. Hash(ll _value1, ull _value2, int _deg)
  75. {
  76. value1 = _value1;
  77. value2 = _value2;
  78. deg = _deg;
  79. }
  80. };
  81. bool operator==(Hash x, Hash y)
  82. {
  83. if (x.deg == -1 || y.deg == -1) return false;
  84. if (x.deg > y.deg) swap(x, y);
  85. x.value1 = (x.value1 * ppows1[y.deg - x.deg]) % Q1;
  86. x.value2 = (x.value2 * ppows2[y.deg - x.deg]);
  87. return x.value1 == y.value1 && x.value2 == y.value2;
  88. }
  89. bool operator<(Hash x, Hash y)
  90. {
  91. return make_pair(x.value1, x.value2) < make_pair(y.value1, y.value2);
  92. }
  93. Hash normalize(Hash x)
  94. {
  95. x.value1 = (x.value1 * ppows1[MAXN - 1 - x.deg]) % Q1;
  96. x.value2 = (x.value2 * ppows2[MAXN - 1 - x.deg]);
  97. x.deg = MAXN - 1;
  98. return x;
  99. }
  100. struct HashString
  101. {
  102. vector<ll>prefHashs1;
  103. vector<ull> prefHashs2;
  104. string s;
  105. HashString(){}
  106. HashString(string& _s)
  107. {
  108. s = _s;
  109. prefHashs1.resize((int)s.length() + 1);
  110. prefHashs2.resize((int)s.length() + 1);
  111. int n = (int)s.length();
  112. for (int i = 1; i <= n; i++)
  113. {
  114. int x = s[i - 1] - 'a' + 1;
  115. prefHashs1[i] = (prefHashs1[i - 1] + 1LL * x * ppows1[i]) % Q1;
  116. prefHashs2[i] = (prefHashs2[i - 1] + 1ULL * x * ppows2[i]);
  117. }
  118. s = '$' + s;
  119. }
  120. Hash getHash(int l, int r)
  121. {
  122. if (r >= (int)s.length()) return Hash(0, 0, -1);
  123. return normalize(Hash((prefHashs1[r] + Q1 - prefHashs1[l - 1]) % Q1, (prefHashs2[r] - prefHashs2[l - 1]), l));
  124. }
  125. string getSubstr(int l, int r)
  126. {
  127. string res;
  128. for (int i = l; i <= r; i++)
  129. {
  130. res += s[i];
  131. }
  132. return res;
  133. }
  134. bool cmpSubstr(int l1, int r1, int l2, int r2)
  135. {
  136. if (s[l1] != s[l2]) return s[l1] < s[l2];
  137. int canGo = min(r1 - l1 + 1, r2 - l2 + 1) + 1;
  138. int l = 1, r = canGo;
  139. while (r - l > 1)
  140. {
  141. int m = (l + r) / 2;
  142. if (getHash(l1, l1 + m - 1) == getHash(l2, l2 + m - 1))
  143. {
  144. l = m;
  145. }
  146. else
  147. {
  148. r = m;
  149. }
  150. }
  151. if (r == canGo)
  152. {
  153. if (r1 - l1 < r2 - l2) return true;
  154. return false;
  155. }
  156. return s[l1 + l] < s[l2 + l];
  157. }
  158. };
  159. HashString hs, hrevs;
  160. ll leftPos[MAXN], rightPos[MAXN], parent[MAXN], lazy[MAXN], cnt[MAXN];
  161. int nextId = 1;
  162. map<Hash, int> pals;
  163. char buf[MAXN];
  164. int gol1[MAXN], gor1[MAXN], gol2[MAXN], gor2[MAXN];
  165. int perm[MAXN];
  166. ll sumCnt[MAXN];
  167. string getString()
  168. {
  169. scanf("%s", buf);
  170. return string(buf);
  171. }
  172. bool cmpPal(int x, int y)
  173. {
  174. return hs.cmpSubstr(leftPos[x], rightPos[x], leftPos[y], rightPos[y]);
  175. }
  176. int main()
  177. {
  178. #ifdef LOCAL
  179. freopen("input.txt", "r", stdin);
  180. #endif
  181. ppows1[0] = 1;
  182. ppows2[0] = 1;
  183. apows[0] = 1;
  184. for (int i = 1; i < MAXN; i++)
  185. {
  186. ppows1[i] = (ppows1[i - 1] * P1) % Q1;
  187. ppows2[i] = (ppows2[i - 1] * P2);
  188. apows[i] = (apows[i - 1] * A) % B;
  189. }
  190. int n, q;
  191. scanf("%d %d\n", &n, &q);
  192. string s = getString();
  193. string revs = s;
  194. reverse(revs.begin(), revs.end());
  195. hs = HashString(s);
  196. hrevs = HashString(revs);
  197. for (int i = 1; i <= n; i++)
  198. {
  199. int l = 1, r = n + 3;
  200. int ri = n - i + 1;
  201. while (r - l > 1)
  202. {
  203. int m = (l + r) / 2;
  204. //cerr << i << " " << ri << " " << m << endl;
  205. //cerr << hs.getHash(i, i + m - 1).value << " " << hrevs.getHash(ri, ri + m - 1).value << endl;
  206. if (hs.getHash(i, i + m - 1) == hrevs.getHash(ri, ri + m - 1))
  207. {
  208. l = m;
  209. }
  210. else
  211. {
  212. r = m;
  213. }
  214. }
  215. gol1[i] = i - l + 1;
  216. gor1[i] = i + l - 1;
  217. // printf("%d %d\n", gol1[i], gor1[i]);
  218. }
  219. for (int i = 1; i < n; i++)
  220. {
  221. if (s[i - 1] != s[i]) continue;
  222. int l = 1, r = n + 3;
  223. int ri = n - i;
  224. while (r - l > 1)
  225. {
  226. int m = (l + r) / 2;
  227. if (hs.getHash(i, i + m - 1) == hrevs.getHash(ri, ri + m - 1))
  228. {
  229. l = m;
  230. }
  231. else
  232. {
  233. r = m;
  234. }
  235. }
  236. gol2[i] = i - l + 2;
  237. gor2[i] = i + l - 1;
  238. //cerr << gol2[i] << " " << gor2[i] << endl;
  239. }
  240. for (int i = 1; i <= n; i++)
  241. {
  242. int cl = gol1[i], cr = gor1[i];
  243. while (true)
  244. {
  245. Hash cur = hs.getHash(cl, cr);
  246. if (pals.find(cur) != pals.end()) break;
  247. pals[cur] = nextId;
  248. leftPos[nextId] = cl;
  249. rightPos[nextId] = cr;
  250. nextId++;
  251. cl++;
  252. cr--;
  253. if (cl > cr) break;
  254. }
  255. }
  256. for (int i = 1; i <= n; i++)
  257. {
  258. int cl = gol2[i], cr = gor2[i];
  259. if (gol2[i] == 0) continue;
  260. while (true)
  261. {
  262. Hash cur = hs.getHash(cl, cr);
  263. if (pals.find(cur) != pals.end()) break;
  264. pals[cur] = nextId;
  265. leftPos[nextId] = cl;
  266. rightPos[nextId] = cr;
  267. nextId++;
  268. cl++;
  269. cr--;
  270. if (cl > cr) break;
  271. }
  272. }
  273. vector<pair<int, int> >toSortLen;
  274. for (int i = 1; i < nextId; i++)
  275. {
  276. toSortLen.push_back(make_pair(rightPos[i] - leftPos[i] + 1, i));
  277. }
  278. sort(toSortLen.begin(), toSortLen.end());
  279. for (int i = 0; i < (int)toSortLen.size(); i++)
  280. {
  281. int x = toSortLen[i].second;
  282. if (rightPos[x] - leftPos[x] + 1 <= 2) continue;
  283. parent[x] = pals[hs.getHash(leftPos[x] + 1, rightPos[x] - 1)];
  284. }
  285. for (int i = 1; i <= n; i++)
  286. {
  287. int x = pals[hs.getHash(gol1[i], gor1[i])];
  288. lazy[x]++;
  289. }
  290. for (int i = 1; i <= n; i++)
  291. {
  292. if (gol2[i] == 0) continue;
  293. int x = pals[hs.getHash(gol2[i], gor2[i])];
  294. lazy[x]++;
  295. }
  296. for (int i = (int)toSortLen.size() - 1; i >= 0; i--)
  297. {
  298. int x = toSortLen[i].second;
  299. cnt[x] = lazy[x];
  300. if (parent[x] != 0)
  301. {
  302. lazy[parent[x]] += lazy[x];
  303. }
  304. }
  305. int sz = nextId - 1;
  306. for (int i = 1; i <= sz; i++)
  307. {
  308. perm[i] = i;
  309. }
  310. sort(perm + 1, perm + 1 + sz, cmpPal);
  311. for (int i = 1; i <= sz; i++)
  312. {
  313. sumCnt[i] = (sumCnt[i - 1] + cnt[perm[i]]);
  314. }
  315. SegmentTree st(n + 1);
  316. st.build(s, 1, 1, n);
  317. for (int i = 1; i <= q; i++)
  318. {
  319. ll x;
  320. scanf("%lld", &x);
  321. int l = 0, r = sz + 1;
  322. if (sumCnt[sz] < x)
  323. {
  324. puts("-1");
  325. continue;
  326. }
  327. while (r - l > 1)
  328. {
  329. int bm = (l + r) / 2;
  330. if (sumCnt[bm] < x)
  331. {
  332. l = bm;
  333. }
  334. else
  335. {
  336. r = bm;
  337. }
  338. }
  339. //cerr << leftPos[perm[r]] << " " << rightPos[perm[r]] << endl;
  340. ResultHash res = st.get(1, 1, n, leftPos[perm[r]], rightPos[perm[r]]);
  341. printf("%lld\n", res.value);
  342. }
  343. return 0;
  344. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement