CF 514 C. Watto and Mechanism(双哈希)
Problem - 514C - Codeforces
大意:给出 n 个字典串 ,现给出 m 个查询串 , 问是否存在字典串与当前查询串仅差一个字母。每个串仅包含 {‘a’ , ‘b’ , ‘c’ } 三个字母 。
思路:考虑哈希 , 先把字典串哈希 , O(n) 预处理查询串 , 然后枚举查询串的每个位置 , 改变当前字母 , O(1) 求出改变后的哈希值与字典串的哈希值比较即可。 需要注意的是 , 本题卡死单哈希 , 要使用双哈希。
还要注意的是 , 如果使用 map 存储 , 一定不要让 map 一直访问空值 , 非常非常慢。
// LUOGU_RID: 122291263
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define int long long
const int N = 6e5 + 10;
const int mod1 = 1e9 + 7;
const int mod2 = 1e9 + 9;
typedef pair<int,int>PII;
//---------------------------------------------------------------------
const int Base = 131;
int base1[N] , h1[N] , base2[N] , h2[N];
inline void init_hash(int n){base1[0] = base2[0] = 1;for(int i = 1 ; i <= n ; i ++) base1[i] = base1[i - 1] * Base % mod1;for(int i = 1 ; i <= n ; i ++) base2[i] = base2[i - 1] * Base % mod2;
}
inline PII get(string s){int n = s.size();h1[0] = h2[0] = 0;for(int i = 1 ; i <= n ; i ++) h1[i] = (h1[i - 1] * Base % mod1 + s[i - 1]) % mod1;for(int i = 1 ; i <= n ; i ++) h2[i] = (h2[i - 1] * Base % mod2 + s[i - 1]) % mod2;int x = ((h1[n] - h1[0] * base1[n]) % mod1 + mod1) % mod1;int y = ((h2[n] - h2[0] * base2[n]) % mod2 + mod2) % mod2;return {x , y};
}
inline void init_s(string s){int now = s.size();h1[0] = h2[0] = 0;for(int i = 1 ; i <= now ; i ++) h1[i] = (h1[i - 1] * Base % mod1 + s[i - 1]) % mod1;for(int i = 1 ; i <= now ; i ++) h2[i] = (h2[i - 1] * Base % mod2 + s[i - 1]) % mod2;
}inline int get_1(int l,int r){return ((h1[r] - h1[l] * base1[r - l]) % mod1 + mod1) % mod1;
}
inline int get_2(int l,int r){return ((h2[r] - h2[l] * base2[r - l]) % mod2 + mod2) % mod2;
}
inline PII get_c(int pos , char c , int n){int x = ((get_1(0 , pos) * Base % mod1 + c) % mod1 * base1[n - pos - 1] % mod1 + get_1(pos + 1 , n)) % mod1;int y = ((get_2(0 , pos) * Base % mod2 + c) % mod2 * base2[n - pos - 1] % mod2 + get_2(pos + 1 , n)) % mod2;return {x , y};
}//---------------------------------------------------------------------
int n , m;
string s;
set<PII>st;signed main(){IOScin >> n >> m;init_hash(N - 10);for(int i = 1 ; i <= n ; i ++){cin >> s;st.insert(get(s));}for(int j = 1 ; j <= m ; j ++){cin >> s;init_s(s);int now = s.size();bool tag = 0;for(int i = 0 ; i < now ; i ++){PII x , y;if(s[i] == 'a'){x = get_c(i , 'b' , now);y = get_c(i , 'c' , now);}if(s[i] == 'b'){x = get_c(i , 'c' , now);y = get_c(i , 'a' , now);}if(s[i] == 'c'){x = get_c(i , 'a' , now);y = get_c(i , 'b' , now);}if(st.find(x) != st.end() || st.find(y) != st.end()){tag = 1;break;}}if(tag) cout << "YES\n";else cout << "NO\n";}return 0;
}
//freopen("文件名.in","r",stdin);
//freopen("文件名.out","w",stdout);