結果
| 問題 |
No.430 文字列検索
|
| コンテスト | |
| ユーザー |
zelosace
|
| 提出日時 | 2020-10-18 15:29:23 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 35 ms / 2,000 ms |
| コード長 | 5,571 bytes |
| コンパイル時間 | 2,236 ms |
| コンパイル使用メモリ | 212,752 KB |
| 最終ジャッジ日時 | 2025-01-15 11:30:36 |
|
ジャッジサーバーID (参考情報) |
judge3 / judge2 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 4 |
| other | AC * 14 |
ソースコード
#include "bits/stdc++.h"
#define REP(i,num) for(ll i=0;i<(num);++i)
#define FOR(i,c,num) for(ll (i)=(c);(i)<(num);++(i))
#define LOOP(i) while(i--)
#define ALL(c) c.begin(),c.end()
#define PRINTALL(c) for(auto pitr=c.begin();pitr!=c.end();++pitr){cout<<*pitr;if(next(pitr,1)!=c.end())cout<<' ';}cout<<endl;
#define PAIRCOMP(c,comp) [](const pair<ll,ll>& lhs,const pair<ll,ll>& rhs){return lhs.c comp rhs.c;}
using namespace std;
using ll = long long;
using vll = vector<ll>;
using vvll = vector<vector<ll>>;
constexpr ll atcoder_mod = 1e9+7;
template<typename T=ll>
T in(){ T x; cin >> x; return (x); }
template<typename T=ll,typename C=vector<T>>
C vecin(int N){ C x(N);REP(i,N){ x[i]=in<T>(); }return x; }
void vout(){ cout << endl; }
template<typename Head,typename... Tail>
void vout(Head&& h,Tail&&... t){ cout << ' ' << h;vout(forward<Tail>(t)...); }
void out(){ cout << endl; }
template<typename Head,typename... Tail>
void out(Head&& h,Tail&&... t){ cout << h;vout(forward<Tail>(t)...); }
template<typename T>
bool chmax(T& a,T b){ if(a<b){ a=b;return true; }return false; }
template<typename T>
bool chmin(T& a,T b){ if(a>b){ a=b;return true; }return false; }
class SuffixArray{
vector<int> InducedSort(vector<int>& str,int char_num,vector<int>& type,vector<int>& lms){
int N=str.size();
vector<int> SA(N,-1),bin(char_num+1,0);
REP(i,N) bin[str[i]+1]++;
REP(i,char_num) bin[i+1] += bin[i];
map<int,int> count;
for(int i=lms.size()-1;i>=0;i--){
int ch = str[lms[i]];
SA[bin[ch+1]-1-count[ch]] = lms[i];
count[ch]++;
}
count.clear();
REP(i,N){
if(SA[i]>0 && type[SA[i]-1]!=0){
int ch = str[SA[i]-1];
SA[bin[ch]+count[ch]] = SA[i]-1;
count[ch]++;
}
}
count.clear();
for(int i=N-1;i>=0;i--){
if(SA[i]>0 && type[SA[i]-1]!=1){
int ch = str[SA[i]-1];
SA[bin[ch+1]-1-count[ch]] = SA[i]-1;
count[ch]++;
}
}
return SA;
}
vector<int> SAIS(vector<int> str,int char_num){
constexpr int S=0,L=1;
if(str.size()==1){
vector<int> ret(1,0);
return ret;
}
int N=str.size();
vector<int> type(N);
type[N-1] = S;
for(int i=N-2;i>=0;i--){
if(str[i]<str[i+1]) type[i] = S;
else if(str[i]>str[i+1]) type[i] = L;
else type[i] = type[i+1];
}
auto isLMS = [&](int i){return (i>0 && type[i-1]==L && type[i]==S);};
vector<int> lms;
REP(i,N){
if(isLMS(i)) lms.push_back(i);
}
auto SA = InducedSort(str,char_num,type,lms);
vector<int> newSA;
REP(i,N){
if(isLMS(SA[i])) newSA.push_back(SA[i]);
}
swap(SA,newSA);
map<int,int> nums;
int num = 0;
nums[SA[0]] = num;
for(int i=0,ei=SA.size()-1;i<ei;i++){
int left=SA[i],right=SA[i+1];
bool diff = false;
for(int d=0;d<N;d++){
if(str[left+d]!=str[right+d] || isLMS(left+d)!=isLMS(right+d)){
diff = true;
break;
}
else if(d>0 && (isLMS(left+d) || isLMS(right+d))){
break;
}
}
if(diff) num++;
nums[right] = num;
}
vector<int> new_lms;
for(auto& x:nums) new_lms.push_back(x.second);
if(num+1<new_lms.size()){
SA = SAIS(new_lms,num+1);
}
else{
newSA.clear();
newSA.resize(num+1);
REP(i,num+1) newSA[new_lms[i]] = i;
swap(SA,newSA);
}
for(int i=0,ei=lms.size();i<ei;i++){
new_lms[i] = lms[SA[i]];
}
SA = InducedSort(str,char_num,type,new_lms);
return SA;
}
vector<int> Construct(int char_num){
int N=S.size();
vector<int> V(N);
REP(i,N) V[i] = S[i];
V.push_back(0);
return SAIS(V,char_num);
}
using Comp = bool (*)(string_view,string);
vector<int>::iterator binary_search(const string& T,Comp comp){
string_view SV(S);
int N=T.size();
auto left=suffix.begin(),right=suffix.end();
auto middle=left+distance(left,right)/2;
while(distance(left,right)>1){
auto SSV = SV.substr(*middle,min(N,SN-(*middle)));
if(comp(SSV,T)){
left = middle;
middle=left+distance(left,right)/2;
}
else{
right = middle;
middle=left+distance(left,right)/2;
}
}
return right;
}
vector<int>::iterator lower_bound(const string& T){
return binary_search(T,[](string_view sv,string s){return sv<s;});
}
vector<int>::iterator upper_bound(const string& T){
return binary_search(T,[](string_view sv,string s){return sv<=s;});
}
public:
SuffixArray(const string& str,int char_num):S(str){
suffix = Construct(char_num);
SN = suffix.size();
}
bool Search(const string& T){
int N=T.size();
auto left=suffix.begin(),right=suffix.end()-1;
auto middle=left+distance(left,right)/2;
while(distance(left,right)>1){
for(int i=0;i<N;i++){
if((*middle)+i>=SN){
left = middle;
middle=left+distance(left,right)/2;
break;
}
if(S[*middle+i]<T[i]){
left = middle;
middle=left+distance(left,right)/2;
break;
}
else if(S[*middle+i]>T[i]){
right = middle;
middle=left+distance(left,right)/2;
break;
}
if(i==N-1){
right = middle;
middle=left+distance(left,right)/2;
}
}
}
bool exist = true;
if(SN-(*right)<N){
exist = false;
}
else{
for(int i=0;i<N;i++){
if(S[*right+i]!=T[i]){
exist = false;
break;
}
}
}
return exist;
}
ll Count(const string& T){
auto first = lower_bound(T);
auto last = upper_bound(T);
return distance(first,last);
}
private:
string S;
vector<int> suffix;
int SN;
};
int main(){
cin.tie(0);
ios::sync_with_stdio(false);
cout<<fixed<<setprecision(10);
string S=in<string>();
SuffixArray SA(S,256);
auto M=in();
ll A=0;
LOOP(M){
string C=in<string>();
A += SA.Count(C);
}
out(A);
return 0;
}
zelosace