説明
�n 個のパターン文字列�1,�2,…,�s1�,s2�,…,sn�および�q クエリが与えられた場合、各クエリにはテキスト文字列�ti�が与えられます。�1 文字列の数�を答えてください。 ��sj は、��ti が��sj の接頭語となるように、∼��s1��∼sn に存在します。
文字列 �t は、�s の末尾からいくつかの (おそらく 0 個の) 連続文字を削除した後、�t と同じである場合に限り、�s の接頭辞になります。
入力文字列のサイズは重要です。たとえば、文字列 Fusu
と文字列 fusu
は異なります。
入力
この問題集のテストポイントには複数のテストデータが含まれています。
入力の最初の行は、データセット数 �T を表す整数です。
データの各セットの形式は次のとおりです。
最初の行は 2 つの整数で、それぞれパターン文字列の数 �n とクエリの数 �q を表します。
次の �n 行には、各行にパターン文字列を表す文字列が含まれています。
次の �q 行はそれぞれ文字列を含み、クエリを表します。
出力
各テストデータの回答は入力順に出力されます。
クエリごとに、答えを表す整数を含む行を出力します。
サンプル1
入力コピー | 出力コピー |
---|---|
3 3 3 fusufusu 戦い 怒っている 戦い 怒っている kkksc 5 2 戦い 戦い AFakeFusu afakefusu ふすいではない偽物 戦い 戦い 1 1 998244353 9 |
2 1 0 1 2 1 |
ヒント
データのサイズと規則
すべてのテスト ポイントについて、1≤�,�,�≤1051≤T,n,q≤105 であり、入力文字列の合計長が 3×1063×106 を超えないことが保証されます。入力文字列には大文字、小文字、数字のみが含まれ、空の文字列は含まれません。
説明する
同期がオフになった後、std の IO は cin/cout を使用します。この質問はスタックしていません。
#include<bits/stdc++.h>
名前空間 std を使用します。
const int N=3e6+10;
int tr[N][100];
int idx=0;
int cnt[N];
int change(char x){ if(x<='z'&&x>='a')return x-'a'; else if(x<='Z'&&x>='A')return x-'A'+26; それ以外の場合は x-'0'+52 を返します。void insert(string b){ int u=0; for(int i=0;i<b.size();i++){ int j=change(b[i]); if(!tr[u][j]){ idx++; tr[u][j]=idx; u =tr[u][j]; cnt[u]++; } }
int search(string b){ int u=0; for(int i=0;b[i];i++){//b[i] == i<b.size() int j=change(b[i]); if(!tr[u][j]){ 0 を返す; u =tr[u][j]; cnt[u]を返します ; void sol(){ for(int i=0;i<=idx;i++){ memset (tr[i],0,sizeof(tr[i])); cnt[i]=0; idx =0; int n,q;cin>>n>>q; 文字列 a; while(n--){ cin>>a; 挿入(a); } while(q--){ cin>>a; cout<<search(a)<<endl;
int
main(){ int t;cin>>t; while(t--)sol(); 0を返します。}