【題解】Codeforces514C. Watto and Mechanism 哈希

給定n,m(3e5)n,m(3e5),先給出nn個文本串,再有mm個查詢串,對每個查詢串詢問:是否存在一個文本串,和查詢串恰有一個字符不同。

字符串總長不超過6e56e5.


hash練手.

採取hash定位+手動複查的方式,跑了1300ms/3000ms.

如果單哈希不復查,會wa.

一個可能的優化是,按長度給字符串分組,碰撞上會好一些。


  1. hash過程括號錯位wa了一次
/* LittleFall : Hello! */
#include <bits/stdc++.h>
using namespace std; using ll = long long; inline int read();
const int M = 300016, MOD = 1000000007;

string tex[M], pat;
set<pair<int,int>> st; //hash_value, id
int hasher(string &str)
{
	ll val = 0;
	for(int i=0; str[i]; ++i)
		val = (val*3+str[i]-'a')%MOD;
	return val;
}
bool check(string &a, string &b)
{
	if(a.size()!=b.size()) return 0;
	int diff = 0;
	for(int i=0; i<(int)a.size(); ++i)
		if(a[i]!=b[i]) ++diff;
	return diff==1;
}
ll p3[M];
int main(void)
{
	#ifdef _LITTLEFALL_
	freopen("in.txt","r",stdin);
    #endif

	p3[0] = 1;
	for(int i=1; i<M; ++i)
		p3[i] = p3[i-1]*3 % MOD;
	int n = read(), m = read();
	for(int i=1; i<=n; ++i)
	{
		cin >> tex[i];
		int val = hasher(tex[i]);
		st.insert({val, i});
	}
	for(int i=1; i<=m; ++i)
	{
		cin >> pat;
		int base_val = hasher(pat);
		int suc = 0;
		for(int j=0; j<(int)pat.size(); ++j)
		{
			for(int c='a'; c<='c'; ++c) if(c!=pat[j])
			{
				ll nval = base_val + p3[pat.size()-1-j]*(c-pat[j]);
				nval = (nval%MOD+MOD)%MOD;
				auto it = st.lower_bound({nval,0});
				while(it!=st.end() && it->first==nval)
				{
					if(check(pat, tex[it->second]))
					{
						suc = 1;
						goto breaker;
					}
					++it;
				}
			}
		}
		breaker:
		printf("%s\n",suc?"YES":"NO" );
	}

    return 0;
}


inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9') {if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章