Advertisement
Guest User

Untitled

a guest
Jul 25th, 2016
56
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.80 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2.  
  3. using namespace std;
  4.  
  5. #ifndef SUFFIXARRAY_H_INCLUDED
  6. #define SUFFIXARRAY_H_INCLUDED
  7.  
  8. #include <algorithm>
  9. #include <vector>
  10.  
  11. class suffix_array
  12. {
  13. public:
  14. std::vector<int> suftab[2];
  15. std::vector<int> order;
  16. std::vector<int> sufarr;
  17. std::vector<int> bucket_count, bucket_size;
  18. std::vector<int> lcp; // lcp(sa[i], sa[i+1]) == sa.lcp[i]
  19. template<class T>
  20. void build_sa(T S[], int N)
  21. {
  22. suftab[0].resize(N);
  23. suftab[1].resize(N);
  24. order.resize(N);
  25. sufarr.resize(N);
  26. bucket_count.resize(N+1);
  27. bucket_size.resize(N+1);
  28. for(int i=0; i<N; i++)
  29. order[i]=S[i];
  30. std::sort(order.begin(), order.end());
  31. for(int i=0; i<N; i++)
  32. suftab[0][i]=std::lower_bound(order.begin(), order.end(), S[i])-order.begin();
  33. int lg=0;
  34. while((1<<lg)<N)
  35. lg++;
  36. int row=0;
  37. for(int hlen=1; hlen<(1<<lg); hlen*=2, row^=1)
  38. {
  39. bucket_count.assign(N+1, 0);
  40. int pos=0;
  41. for(int i=0; i+hlen<N; i++)
  42. bucket_count[suftab[row][i+hlen]+1]++;
  43. for(int i=N-hlen; i<N; i++)
  44. order[pos++]=i;
  45. bucket_count[0]=pos;
  46. std::partial_sum(bucket_count.begin(), bucket_count.end(), bucket_size.begin());
  47. for(int i=0; i+hlen<N; i++)
  48. order[bucket_size[suftab[row][i+hlen]]++]=i;
  49. bucket_count[0]=0;
  50. for(int i=0; i<hlen; i++)
  51. bucket_count[suftab[row][i]+1]++;
  52. std::partial_sum(bucket_count.begin(), bucket_count.end(), bucket_size.begin());
  53. for(int i=0; i<N; i++)
  54. sufarr[bucket_size[suftab[row][order[i]]]++]=order[i];
  55. int prev_a=-1, prev_b=-1, prev_c=-1;
  56. for(int i=0; i<N; i++)
  57. {
  58. const int x=sufarr[i];
  59. const int now_a=suftab[row][x];
  60. const int now_b=(x+hlen<N?suftab[row][x+hlen]:-1);
  61. prev_c+=now_a!=prev_a || now_b!=prev_b;
  62. suftab[row^1][x]=prev_c;
  63. prev_a=now_a;
  64. prev_b=now_b;
  65. }
  66. }
  67. if(row==1)
  68. suftab[0].swap(suftab[1]);
  69. }
  70. template<class T>
  71. void build(T S[], int N)
  72. {
  73. build_sa(S, N);
  74. lcp.resize(sufarr.size());
  75. for(int i=0, len=0; i<N; i++)
  76. {
  77. if(get_rank(i)==N-1)
  78. len=0;
  79. else
  80. {
  81. int j=sufarr[get_rank(i)+1];
  82. int maxl=N-std::max(i, j);
  83. while(len<maxl && S[i+len]==S[j+len])
  84. len++;
  85. lcp[get_rank(i)]=len;
  86. if(len>0)
  87. len--;
  88. }
  89. }
  90. }
  91. inline int get_rank(const int& idx) const
  92. {
  93. return suftab[0][idx];
  94. }
  95. int operator[] (const int& idx) const
  96. {
  97. return sufarr[idx];
  98. }
  99. };
  100.  
  101. #endif // SUFFIXARRAY_H_INCLUDED
  102.  
  103. const int HASH_MAXN=400001;
  104. const int X=129;
  105. const int MOD1=1000000009;
  106. const int MOD2=1000000021;
  107. int P1[HASH_MAXN];
  108. int P2[HASH_MAXN];
  109.  
  110. struct Hash
  111. {
  112. int len, val0, val1;
  113. Hash():
  114. len(0),
  115. val0(0),
  116. val1(0)
  117. {
  118. //
  119. }
  120. Hash(int val):
  121. len(1),
  122. val0(val),
  123. val1(val)
  124. {
  125. //
  126. }
  127. Hash operator+ (const Hash& other) const
  128. {
  129. Hash ret;
  130. ret.len=len+other.len;
  131. ret.val0=(other.val0+1LL*P1[other.len]*val0)%MOD1;
  132. ret.val1=(other.val1+1LL*P2[other.len]*val1)%MOD2;
  133. return ret;
  134. }
  135. Hash operator- (const Hash& other) const
  136. {
  137. Hash ret;
  138. ret.len=len-other.len;
  139. ret.val0=val0-1LL*P1[len-other.len]*other.val0%MOD1;
  140. if(ret.val0<0)
  141. ret.val0+=MOD1;
  142. ret.val1=val1-1LL*P2[len-other.len]*other.val1%MOD2;
  143. if(ret.val1<0)
  144. ret.val1+=MOD2;
  145. return ret;
  146. }
  147. bool operator< (const Hash& other) const
  148. {
  149. if(len!=other.len)
  150. return len<other.len;
  151. if(val0!=other.val0)
  152. return val0<other.val0;
  153. return val1<other.val1;
  154. }
  155. bool operator== (const Hash& other) const
  156. {
  157. return len==other.len && val0==other.val0 && val1==other.val1;
  158. }
  159. bool operator!= (const Hash& other) const
  160. {
  161. return !(*this==other);
  162. }
  163. };
  164.  
  165. void init_hash()
  166. {
  167. P1[0]=1;
  168. for(int i=1; i<HASH_MAXN; i++)
  169. P1[i]=1LL*P1[i-1]*X%MOD1;
  170. P2[0]=1;
  171. for(int i=1; i<HASH_MAXN; i++)
  172. P2[i]=1LL*P2[i-1]*X%MOD2;
  173. }
  174.  
  175. static int _hash_initialized=(init_hash(), 0);
  176.  
  177. int tlen;
  178. int msuf[200001];
  179. Hash H[200001];
  180. Hash R[200001];
  181.  
  182. Hash get_substr(int l, int r)
  183. {
  184. if(l==0)
  185. return H[r];
  186. return H[r]-H[l-1];
  187. }
  188.  
  189. Hash get_r_substr(int l, int r)
  190. {
  191. if(r==tlen-1)
  192. return R[l];
  193. return R[l]-R[r+1];
  194. }
  195.  
  196. Hash get_hash(vector<pair<int, int>>& a, int l)
  197. {
  198. Hash h;
  199. for(auto& it: a)
  200. {
  201. if(l==0)
  202. break;
  203. if(abs(it.first-it.second)+1<=l)
  204. {
  205. l-=abs(it.first-it.second)+1;
  206. if(it.first>it.second)
  207. h=h+get_r_substr(it.second, it.first);
  208. else
  209. h=h+get_substr(it.first, it.second);
  210. }
  211. else
  212. {
  213. if(it.first>it.second)
  214. h=h+get_r_substr(it.first-l+1, it.first);
  215. else
  216. h=h+get_substr(it.first, it.first+l-1);
  217. break;
  218. }
  219. }
  220. return h;
  221. }
  222.  
  223. char get_char(string& t, vector<pair<int, int>>& a, int l)
  224. {
  225. for(auto& it: a)
  226. {
  227. if(abs(it.first-it.second)+1<=l)
  228. l-=abs(it.first-it.second)+1;
  229. else
  230. {
  231. if(it.first>it.second)
  232. return t[it.first-l];
  233. return t[it.first+l];
  234. }
  235. }
  236. return '?';
  237. }
  238.  
  239. vector<pair<int, int>> get_min(string& t, vector<pair<int, int>> a, vector<pair<int, int>> b)
  240. {
  241. int la=0, lb=0;
  242. for(auto& it: a)
  243. la+=abs(it.first-it.second)+1;
  244. for(auto& it: b)
  245. lb+=abs(it.first-it.second)+1;
  246. assert(la==lb);
  247. int lo=0, mid, hi=min(la, lb);
  248. while(lo<hi)
  249. {
  250. mid=(lo+hi+1)/2;
  251. if(get_hash(a, mid)==get_hash(b, mid))
  252. lo=mid;
  253. else
  254. hi=mid-1;
  255. }
  256. if(lo==min(la, lb) || get_char(t, a, lo)<get_char(t, b, lo))
  257. return a;
  258. return b;
  259. }
  260.  
  261. pair<int, string> solve(string s, string t)
  262. {
  263. tlen=t.length();
  264. reverse(s.begin(), s.end());
  265. string S=t+'#'+s;
  266. suffix_array sa;
  267. sa.build(S.c_str(), S.length());
  268. for(int i=0; i<=(int)t.length(); i++)
  269. msuf[i]=0;
  270. int len=0;
  271. for(int i=0; i<(int)S.length(); i++)
  272. {
  273. int suf=sa[i];
  274. if(suf<(int)t.length())
  275. msuf[suf]=max(msuf[suf], len);
  276. else if(suf>(int)t.length() && i+1<(int)S.length())
  277. len=max(len, sa.lcp[i]);
  278. if(i+1<(int)S.length())
  279. len=min(len, sa.lcp[i]);
  280. }
  281. len=0;
  282. for(int i=(int)S.length()-1; i>=0; i--)
  283. {
  284. int suf=sa[i];
  285. if(suf<(int)t.length())
  286. msuf[suf]=max(msuf[suf], len);
  287. else if(suf>(int)t.length() && i-1>=0)
  288. len=max(len, sa.lcp[i-1]);
  289. if(i-1>=0)
  290. len=min(len, sa.lcp[i-1]);
  291. }
  292. Hash h;
  293. for(int i=0; i<(int)t.length(); i++)
  294. {
  295. h=h+Hash(t[i]);
  296. H[i]=h;
  297. }
  298. h=Hash();
  299. for(int i=(int)t.length()-1; i>=0; i--)
  300. {
  301. h=h+Hash(t[i]);
  302. R[i]=h;
  303. }
  304. vector<pair<int, int>> ans2;
  305. int ans=0;
  306. for(int i=0; i<(int)t.length(); i++) if(msuf[i])
  307. {
  308. if(msuf[i]*2>ans)
  309. {
  310. ans=msuf[i]*2;
  311. ans2={{i, i+msuf[i]-1}, {i+msuf[i]-1, i}};
  312. }
  313. else if(msuf[i]*2==ans)
  314. ans2=get_min(t, ans2, {{i, i+msuf[i]-1}, {i+msuf[i]-1, i}});
  315. }
  316. // one center
  317. for(int i=0; i<(int)t.length(); i++)
  318. {
  319. int l=min(i+1, (int)t.length()-i);
  320. int lo=1, mid, hi=l;
  321. while(lo<hi)
  322. {
  323. mid=(lo+hi+1)/2;
  324. if(get_r_substr(i-mid+1, i)==get_substr(i, i+mid-1))
  325. lo=mid;
  326. else
  327. hi=mid-1;
  328. }
  329. if(msuf[i+lo])
  330. {
  331. int v=2*lo-1+2*msuf[i+lo];
  332. if(v>ans)
  333. {
  334. ans=v;
  335. ans2={{i+lo+msuf[i+lo]-1, i+lo}, {i-lo+1, i+lo+msuf[i+lo]-1}};
  336. }
  337. else if(v==ans)
  338. ans2=get_min(t, ans2, {{i+lo+msuf[i+lo]-1, i+lo}, {i-lo+1, i+lo+msuf[i+lo]-1}});
  339. }
  340. }
  341. // two centers
  342. for(int i=0; i<(int)t.length()-1; i++)
  343. {
  344. int l=min(i+1, (int)t.length()-(i+1));
  345. int lo=0, mid, hi=l;
  346. while(lo<hi)
  347. {
  348. mid=(lo+hi+1)/2;
  349. if(get_r_substr(i-mid+1, i)==get_substr(i+1, i+1+mid-1))
  350. lo=mid;
  351. else
  352. hi=mid-1;
  353. }
  354. if(msuf[i+1+lo])
  355. {
  356. int v=2*lo+2*msuf[i+1+lo];
  357. if(v>ans)
  358. {
  359. ans=v;
  360. ans2={{i+1+lo+msuf[i+1+lo]-1, i+1+lo}, {i-lo+1, i+1+lo+msuf[i+1+lo]-1}};
  361. }
  362. else if(v==ans)
  363. ans2=get_min(t, ans2, {{i+1+lo+msuf[i+1+lo]-1, i+1+lo}, {i-lo+1, i+1+lo+msuf[i+1+lo]-1}});
  364. }
  365. }
  366. string res="";
  367. for(auto& it: ans2)
  368. {
  369. if(it.first>it.second)
  370. {
  371. for(int i=it.first; i>=it.second; i--)
  372. res+=t[i];
  373. }
  374. else
  375. {
  376. for(int i=it.first; i<=it.second; i++)
  377. res+=t[i];
  378. }
  379. }
  380. return make_pair(ans, res);
  381. }
  382.  
  383. string _main()
  384. {
  385. string a, b;
  386. cin>>a>>b;
  387. if(a.length()<=50 && b.length()<=50)
  388. {
  389. string ans="";
  390. for(int la=1; la<=(int)a.length(); la++)
  391. {
  392. for(int i=0; i+la-1<(int)a.length(); i++)
  393. {
  394. for(int lb=1; lb<=(int)b.length(); lb++)
  395. {
  396. for(int j=0; j+lb-1<(int)b.length(); j++)
  397. {
  398. string s=a.substr(i, la)+b.substr(j, lb);
  399. string t=s;
  400. reverse(t.begin(), t.end());
  401. if(s==t)
  402. {
  403. if(s.length()>ans.length())
  404. ans=s;
  405. else if(s.length()==ans.length())
  406. ans=min(ans, s);
  407. }
  408. }
  409. }
  410. }
  411. }
  412. if(ans.empty())
  413. return "-1";
  414. return ans;
  415. }
  416. auto x=solve(a, b);
  417. reverse(a.begin(), a.end());
  418. reverse(b.begin(), b.end());
  419. auto y=solve(b, a);
  420. reverse(y.second.begin(), y.second.end());
  421. if(max(x.first, y.first)==0)
  422. return "-1";
  423. if(x.first>y.first)
  424. return x.second;
  425. else if(x.first<y.first)
  426. return y.second;
  427. return min(x.second, y.second);
  428. }
  429.  
  430. int main()
  431. {
  432. int Q;
  433. scanf("%d", &Q);
  434. while(Q--)
  435. cout<<_main()<<endl;
  436. return 0;
  437. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement