rainygame @ 2023-08-07 19:53:50
过了中间四个点。
思路:
对于每个前缀,用哈希存一遍。可以发现总共最多只会存
储存我是用双哈希,因为直接比较字符串的复杂度开销很大。查询的期望时间复杂度是 set
去重),其中我设
清空我只清空用过的,顶多就只会清空 list
中的顶多
总的时间复杂度应该是
代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int MOD(1e6+7);
const int BASE1(131);
const int BASE2(13331);
int t, n, q, ha1, base1;
unsigned int ha2, base2;
string str, tmp;
list<pair<unsigned int, int>> li[MOD];
vector<int> vec;
void clear(){
for (int i: vec) li[i].clear();
vec.clear();
}
void insert(string str, int ha1, int ha2, int ind){
vec.push_back(ha1);
li[ha1].push_back({ha2, ind});
}
int query(string str){
set<int> st;
ha1 = ha2 = 0;
base1 = base2 = 1;
for (char i: str){
ha1 = (ha1 + i * base1) % MOD;
base1 = (base1 * BASE1) % MOD;
ha2 += i * base2;
base2 *= BASE2;
}
for (auto i: li[ha1]){
if (i.first == ha2) st.insert(i.second);
}
return st.size();
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> t;
while (t--){
cin >> n >> q;
clear();
for (int i(1); i<=n; ++i){
cin >> str;
tmp = "";
ha1 = ha2 = 0;
base1 = base2 = 1;
for (char j: str){
ha1 = (ha1 + j * base1) % MOD;
base1 = (base1 * BASE1) % MOD;
ha2 += j * base2;
base2 *= BASE2;
tmp += j;
insert(tmp, ha1, ha2, i);
}
}
while (q--){
cin >> str;
cout << query(str) << '\n';
}
}
return 0;
}
by esquigybcu @ 2023-08-07 19:57:41
你模数太小了,双哈希也大概只需要 1e6 次就寄了
by fenwicktree @ 2023-08-07 20:00:11
模数开大一点,我有一次998244353都出事了
by rainygame @ 2023-08-07 20:04:51
@const_long_long 我开大了模数,本地测 #1 依旧 3.7s
by rainygame @ 2023-08-07 20:06:17
@const_long_long 开到了 9982443,继续就没法再开了
by rainygame @ 2023-08-07 20:10:33
更新:https://www.luogu.com.cn/paste/tk8rrmyp
by esquigybcu @ 2023-08-07 20:13:04
@rainygame 用 list 的目的在于?
by Iniaugoty @ 2023-08-07 20:13:34
@rainygame 再多两个模数试试?话说这题好像直接map都比我的Trie快
by rainygame @ 2023-08-07 20:15:22
@esquigybcu 哈希表呀
by rainygame @ 2023-08-07 20:18:01
@gty314159 能否给一下 map
的代码,感觉我这个可能哪里搞错了
by esquigybcu @ 2023-08-07 20:22:11
@rainygame 这个 list 还是换成 vector 吧