結果
問題 | No.515 典型LCP |
ユーザー | btk |
提出日時 | 2017-05-07 16:31:37 |
言語 | C++14 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 778 ms / 1,000 ms |
コード長 | 7,109 bytes |
コンパイル時間 | 1,942 ms |
コンパイル使用メモリ | 178,024 KB |
実行使用メモリ | 152,708 KB |
最終ジャッジ日時 | 2024-09-14 14:47:13 |
合計ジャッジ時間 | 9,226 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge3 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 778 ms
152,500 KB |
testcase_01 | AC | 615 ms
152,708 KB |
testcase_02 | AC | 339 ms
134,212 KB |
testcase_03 | AC | 2 ms
5,376 KB |
testcase_04 | AC | 2 ms
5,376 KB |
testcase_05 | AC | 386 ms
135,456 KB |
testcase_06 | AC | 383 ms
135,324 KB |
testcase_07 | AC | 373 ms
135,452 KB |
testcase_08 | AC | 411 ms
135,456 KB |
testcase_09 | AC | 279 ms
134,336 KB |
testcase_10 | AC | 274 ms
134,600 KB |
testcase_11 | AC | 272 ms
134,600 KB |
testcase_12 | AC | 277 ms
134,472 KB |
testcase_13 | AC | 280 ms
134,432 KB |
testcase_14 | AC | 175 ms
134,456 KB |
testcase_15 | AC | 363 ms
135,584 KB |
testcase_16 | AC | 366 ms
135,580 KB |
ソースコード
#include<bits/stdc++.h> using namespace std; typedef long long LL; #define fin "\n" #define FOR(i,bg,ed) for(int i=(bg);i<(ed);i++) #define REP(i,n) FOR(i,0,n) #define ALL(v) (v).begin(),(v).end() #define fi first #define se second #define pb push_back #define DEBUG if(0) #define REC(ret, ...) std::function<ret (__VA_ARGS__)> template <typename T>inline bool chmin(T &l,T r) {bool a=l>r;if(a)l=r;return a;} template <typename T>inline bool chmax(T &l,T r) {bool a=l<r;if(a)l=r;return a;} template <typename T> istream& operator>>(istream &is,vector<T> &v){ for(auto &it:v)is>>it; return is; } /* sa[0]=n //空文字列 lcp[i]:=suffix[sa[i]]とsuffix[sa[i+1]]の共通高さ */ namespace latte{ void create_begin_bucket(vector<int>&v,vector<int>&bucket){ fill(bucket.begin(),bucket.end(),0); for(int i=0;i<v.size();i++)bucket[v[i]]++; int sum=0; for(int i=0;i<bucket.size();i++){bucket[i]+=sum;swap(sum,bucket[i]);} } void create_end_bucket(vector<int>&v,vector<int>&bucket){ fill(bucket.begin(),bucket.end(),0); for(int i=0;i<v.size();i++)bucket[v[i]]++; for(int i=1;i<bucket.size();i++)bucket[i]+=bucket[i-1]; } void induced_sort(vector<int>&v,vector<int>&sa,int mv,vector<int>&bucket,vector<int>&is_l){ create_begin_bucket(v,bucket); for(int i=0;i<v.size();i++)if(sa[i]>0&&is_l[sa[i]-1])sa[bucket[v[sa[i]-1]]++]=sa[i]-1; } void invert_induced_sort(vector<int>&v,vector<int>&sa,int mv,vector<int>&bucket,vector<int>&is_l){ create_end_bucket(v,bucket); for(int i=v.size()-1;i>=0;i--)if(sa[i]>0&&!is_l[sa[i]-1])sa[--bucket[v[sa[i]-1]]]=sa[i]-1; } vector<int>sa_is(vector<int>v,int mv){ if(v.size()==1)return vector<int>(1,0); vector<int>is_l(v.size()); vector<int>bucket(mv+1); vector<int>sa(v.size(),-1); auto is_lms=[&](int x)->bool{return x>0&&is_l[x-1]&&!is_l[x];}; is_l[v.size()-1]=0; for(int i=v.size()-2;i>=0;i--)is_l[i]=v[i]>v[i+1]||(v[i]==v[i+1]&&is_l[i+1]); create_end_bucket(v,bucket); for(int i=0;i<v.size();i++)if(is_lms(i))sa[--bucket[v[i]]]=i; induced_sort(v,sa,mv,bucket,is_l); invert_induced_sort(v,sa,mv,bucket,is_l); int cur=0; vector<int>order(v.size()); for(int i=0;i<v.size();i++)if(is_lms(i))order[i]=cur++; vector<int>next_v(cur); cur=-1; int prev=-1; for(int i=0;i<v.size();i++){ if(!is_lms(sa[i]))continue; bool diff=false; for(int d=0;d<v.size();d++){ if(prev==-1||v[sa[i]+d]!=v[prev+d]||is_l[sa[i]+d]!=is_l[prev+d]){ diff=true; break; } else if(d>0&&is_lms(sa[i]+d))break; } if(diff){cur++;prev=sa[i];} next_v[order[sa[i]]]=cur; } vector<int>re_order(next_v.size()); for(int i=0;i<v.size();i++)if(is_lms(i))re_order[order[i]]=i; vector<int>next_sa=sa_is(next_v,cur); create_end_bucket(v,bucket); for(int i=0;i<sa.size();i++)sa[i]=-1; for(int i=next_sa.size()-1;i>=0;i--)sa[--bucket[v[re_order[next_sa[i]]]]]=re_order[next_sa[i]]; induced_sort(v,sa,mv,bucket,is_l); invert_induced_sort(v,sa,mv,bucket,is_l); return sa; } vector<int> sa_is(string &s){ vector<int>v(s.size()+1); for(int i=0;i<s.size();i++)v[i]=s[i]; return sa_is(v,*max_element(v.begin(),v.end())); } } namespace SA { int n, k; int R[912345]; int T[912345]; bool compare_sa(int i, int j) { if (R[i] != R[j])return R[i] < R[j]; else { int ri = i + k <= n ? R[i + k] : -1; int rj = j + k <= n ? R[j + k] : -1; return ri < rj; } } vector<int> construct_sa(string& S) { return latte::sa_is(S); n = S.size(); vector<int> sa(n + 1); for (int i = 0; i <= n; i++) { sa[i] = i; R[i] = i < n ? S[i] : -1; } for (k = 1; k <= n; k *= 2) { sort(sa.begin(), sa.end(), compare_sa); T[sa[0]] = 0; for (int i = 1; i <= n; i++) T[sa[i]] = T[sa[i - 1]] + (compare_sa(sa[i - 1], sa[i]) ? 1 : 0); for (int i = 0; i <= n; i++) R[i] = T[i]; } return sa; } vector<int> construct_lcp(string& S, vector<int> &sa) { n = S.size(); for (int i = 0; i <= n; i++)R[sa[i]] = i; int h = 0; vector<int> lcp(n + 1, 0); for (int i = 0; i < n; i++) { int j = sa[R[i] - 1]; if (h > 0)h--; for (; j + h < n&&i + h < n; h++) { if (S[j + h] != S[i + h])break; } lcp[R[i] - 1] = h; } return lcp; } } namespace TABLE{ #define SIZE 20000000 int mem[2][SIZE]; //#defube CNT 100 //int cnt=0; //int mems[CNT][SIZE]; }; template <typename T> class min_sparse_table{ private: T *L,*R;int _size; void build(){ for(int k = _size,b=1 ;b*2<=_size; k+=_size,b<<=1) for(int i = 0; i < _size; i++){ if(i+b*2<=_size) L[k+i]=min(L[k-_size+i],L[k-_size+i+b]); if(i-b*2>=-1) R[k+i]=min(R[k-_size+i],R[k-_size+i-b]); } } public:/*methods*/ int size(){return _size;} T get(int l,int r){ int k=(31-__builtin_clz(r-l+1))*_size; return min(L[k+l],R[k+r]); } min_sparse_table(std::vector<T> &v) :L(TABLE::mem[0]),R(TABLE::mem[1]){ _size=v.size(); for(int i = 0; i < _size; i++)L[i]=R[i]=v[i]; build(); } min_sparse_table(T* v,int n) :L(TABLE::mem[0]),R(TABLE::mem[1]){ _size=n; for(int i = 0; i < _size; i++)L[i]=R[i]=v[i]; build(); } }; char s[912345]; int main(){ int N; scanf("%d",&N); char *ss=s; vector<int> id(N+1); int len=0; REP(i,N){ scanf("%s",ss); id[i]=len; while(*ss !='\0'){ ss++;len++; } *(ss++)='$';len++; } id.back()=len; *(ss++)='\0'; string str=s; LL x,d,M; scanf("%lld %lld %lld",&M,&x,&d); auto sa = SA::construct_sa(str); auto cww=sa; REP(i,sa.size()){ cww[sa[i]]=i; } auto lcp = SA::construct_lcp(str,sa); min_sparse_table<int> rmq(lcp); // return 0; LL res=0; REP(q,M){ LL i = x/(N-1)+1; LL j = x%(N-1)+1; if(i>j)swap(i,j); else j++; i--,j--; int ij=min(id[i+1]-id[i],id[j+1]-id[j])-1; i=cww[id[i]]; j=cww[id[j]]; if(i>j)swap(i,j); if(i==j){ res+=id[i+1]-id[i]-1; //cout<<"a"<<endl; } else { int k=rmq.get(i,j-1); res+=min(k,ij); //cout<<k<<endl; } x=(x+d)%(N*(N-1ll)); } printf("%lld\n",res); return 0; }