結果
問題 | No.515 典型LCP |
ユーザー | chocorusk |
提出日時 | 2019-10-27 14:48:45 |
言語 | C++14 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 817 ms / 1,000 ms |
コード長 | 5,286 bytes |
コンパイル時間 | 1,746 ms |
コンパイル使用メモリ | 137,772 KB |
実行使用メモリ | 99,608 KB |
最終ジャッジ日時 | 2024-09-14 21:03:01 |
合計ジャッジ時間 | 8,685 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge1 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 817 ms
98,124 KB |
testcase_01 | AC | 512 ms
99,608 KB |
testcase_02 | AC | 281 ms
94,100 KB |
testcase_03 | AC | 2 ms
5,376 KB |
testcase_04 | AC | 2 ms
5,376 KB |
testcase_05 | AC | 398 ms
97,224 KB |
testcase_06 | AC | 406 ms
97,224 KB |
testcase_07 | AC | 407 ms
97,228 KB |
testcase_08 | AC | 424 ms
97,356 KB |
testcase_09 | AC | 234 ms
94,076 KB |
testcase_10 | AC | 227 ms
93,984 KB |
testcase_11 | AC | 228 ms
93,984 KB |
testcase_12 | AC | 227 ms
93,988 KB |
testcase_13 | AC | 227 ms
93,960 KB |
testcase_14 | AC | 146 ms
94,024 KB |
testcase_15 | AC | 393 ms
97,220 KB |
testcase_16 | AC | 398 ms
97,232 KB |
ソースコード
#include <cstdio> #include <cstring> #include <iostream> #include <string> #include <cmath> #include <bitset> #include <vector> #include <map> #include <set> #include <queue> #include <deque> #include <algorithm> #include <complex> #include <unordered_map> #include <unordered_set> #include <random> #include <cassert> #include <fstream> #include <utility> #include <functional> #include <time.h> #include <stack> #define popcount __builtin_popcount using namespace std; typedef long long int ll; typedef pair<int, int> P; //https://judge.yosupo.jp/submission/877 #define MP make_pair #define fi first #define se second #define ALL(a) (a).begin(),(a).end() struct SuffixArray{ ll size; string s; vector<ll>data; SuffixArray(string S):size(S.size()),s(S){ s += '$'; vector<ll>input(s.size()); for(ll i=0;i<s.size();i++)input[i] = s[i]; data = induced_sort(input, 200); data.erase(data.begin()); } vector<ll> induced_sort(vector<ll>t, ll kind){ ll sz = t.size(); vector<bool>ls(sz);//trueはL型,falseはS型 for(ll i = sz-1;i>=0;i--){ if(i==sz-1)ls[i] = false; else{ if(t[i]!=t[i+1])ls[i] = (t[i] > t[i+1]); else ls[i] = ls[i+1]; } } vector<ll>cnt(kind); for(ll i=0;i<sz;i++)cnt[t[i]]++; vector<P>lr(kind,MP(-1,-1)); for(ll i=1;i<kind;i++){ if(cnt[i]==0)lr[i] = lr[i-1]; else lr[i] = make_pair(lr[i-1].se + 1, lr[i-1].se + cnt[i]); } vector<ll>lmsidx,ret(sz,-1); for(ll i=0;i<sz-1;i++){ if(ls[i]&&!ls[i+1]){ ret[lr[t[i+1]].fi+cnt[t[i+1]]-1]=i+1; cnt[t[i+1]]--; lmsidx.push_back(i+1); } } fill(ALL(cnt),0); for(ll i=0;i<sz;i++){ if(ret[i]>=1&&ls[ret[i]-1]){ ret[lr[t[ret[i]-1]].fi+cnt[t[ret[i]-1]]]=ret[i]-1; cnt[t[ret[i]-1]]++; if(i!=0&&!ls[ret[i]])ret[i]=-1; } } fill(ALL(cnt),0); for(ll i=sz-1;i>=1;i--){ if(ret[i]>=1&&!ls[ret[i]-1]){ ret[lr[t[ret[i]-1]].se-cnt[t[ret[i]-1]]]=ret[i]-1; cnt[t[ret[i]-1]]++; } } vector<ll>rev_lmsidx(sz,-1),lmsinput(lmsidx.size(),-1); for(ll i=0;i<lmsidx.size();i++)rev_lmsidx[lmsidx[i]] = i; ll kindnum=1; lmsinput[rev_lmsidx[ret[0]]] = 1; vector<ll>comp(t.begin()+ret[0],t.end()); for(ll i=1;i<sz;i++){ if(ret[i]>=1&&ls[ret[i]-1]&&!ls[ret[i]]){ vector<ll>tmp(t.begin()+ret[i],t.begin()+lmsidx[rev_lmsidx[ret[i]]+1]+1); if(comp != tmp){ kindnum++; comp = tmp; } lmsinput[rev_lmsidx[ret[i]]] = kindnum; } } vector<ll>output; if(kindnum==lmsidx.size()){ output.assign(kindnum,-1); for(ll i=0;i<lmsinput.size();i++)output[lmsinput[i]-1]=i; } else output = induced_sort(lmsinput,kindnum+1); fill(ALL(cnt),0), fill(ALL(ret),-1); for(ll i=output.size()-1;i>=0;i--){ ll tmp=lmsidx[output[i]]; ret[lr[t[tmp]].se - cnt[t[tmp]]]=tmp; cnt[t[tmp]]++; } fill(ALL(cnt),0); for(ll i=0;i<sz;i++){ if(ret[i]>=1&&ls[ret[i]-1]){ ret[lr[t[ret[i]-1]].fi+cnt[t[ret[i]-1]]]=ret[i]-1; cnt[t[ret[i]-1]]++; if(i!=0&&!ls[ret[i]])ret[i]=-1; } } fill(ALL(cnt),0); for(ll i=sz-1;i>=1;i--){ if(ret[i]>=1&&!ls[ret[i]-1]){ ret[lr[t[ret[i]-1]].se-cnt[t[ret[i]-1]]]=ret[i]-1; cnt[t[ret[i]-1]]++; } } return ret; } ll operator[](const int &k) const{ return data[k]; } }; struct LCP{ SuffixArray sa; vector<int> lcp, rk; LCP(SuffixArray sa):sa(sa), lcp(sa.size), rk(sa.size+1){ rk[sa.size]=0; for(int i=0; i<sa.size; i++){ rk[sa[i]]=i+1; } int h=0; lcp[0]=0; for(int i=0; i<sa.size; i++){ int j=sa[rk[i]-2]; if(h>0) h--; for(; j+h<sa.size && i+h<sa.size; h++){ if(sa.s[j+h]!=sa.s[i+h]) break; } lcp[rk[i]-1]=h; } } int operator[](const int &k) const{ return lcp[k]; } }; vector<vector<int>> spt; vector<int> vlog; void sparsetable_build(const vector<int> &v){ int b=0, n=v.size(); while((1<<b)<=n) b++; spt.resize(b, vector<int>(n)); for(int i=0; i<n; i++) spt[0][i]=v[i]; for(int i=1; i<b; i++){ for(int j=0; j+(1<<i)<=n; j++){ spt[i][j]=min(spt[i-1][j], spt[i-1][j+(1<<(i-1))]); } } vlog.resize(n+1); for(int i=2; i<=n; i++) vlog[i]=vlog[i>>1]+1; } inline int rmq(int l, int r){ int b=vlog[r-l]; return min(spt[b][l], spt[b][r-(1<<b)]); } int main() { int n; cin>>n; string s; int id[100010], len[100010]; for(int i=0; i<n; i++){ string si; cin>>si; s+=si; len[i]=si.size(); id[i+1]=id[i]+len[i]; } SuffixArray sa(s); LCP lcp(sa); vector<int> v(s.size()); for(int i=0; i<s.size(); i++) v[i]=lcp[i]; sparsetable_build(v); int m; ll x, d; cin>>m>>x>>d; ll ans=0; for(int i=0; i<m; i++){ int p=x/(n-1), q=x%(n-1); if(p>q) swap(p, q); else q++; x=(x+d)%((ll)n*(n-1)); int p1=lcp.rk[id[p]], q1=lcp.rk[id[q]]; if(p1>q1) swap(p1, q1); ans+=min({len[p], len[q], rmq(p1, q1)}); } cout<<ans<<endl; return 0; }