結果
| 問題 |
No.515 典型LCP
|
| コンテスト | |
| ユーザー |
btk
|
| 提出日時 | 2017-05-06 00:38:04 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
RE
(最新)
AC
(最初)
|
| 実行時間 | - |
| コード長 | 7,107 bytes |
| コンパイル時間 | 1,958 ms |
| コンパイル使用メモリ | 177,712 KB |
| 実行使用メモリ | 146,416 KB |
| 最終ジャッジ日時 | 2024-09-14 10:08:01 |
| 合計ジャッジ時間 | 8,860 ms |
|
ジャッジサーバーID (参考情報) |
judge4 / judge6 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 13 RE * 2 |
ソースコード
#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 16000000
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-1));
}
printf("%lld\n",res);
return 0;
}
btk