19上海icpc網絡賽 G Substring哈希好題

這道題乍一看不能hash實際上最多sqrt(1e5)種長度,所以1e4*sqrt(1e5)就可以了
但這種hash第一次見

#include <bits/stdc++.h>
using namespace std;
#define ull unsigned long long
#define forn(i,n) for(int i=0;i<n;i++)
#define for1(i,n) for(int i=1;i<=n;i++)
#define IO ios::sync_with_stdio(false);cin.tie(0)
const int maxn = 2e4+5;
const int maxm = 1e5+5;
const int seed = 131;

unordered_map<ull,int>mp[26][26];
unordered_map<ull,bool>vis[26][26];
string z,s;
int ans[maxn],n;
ull p[30];
struct Q{
    int id,len,l,r;
    ull has;
}q[maxn];
bool cmp(Q a,Q b){
    return a.len<b.len;
}

void getans(int x){
    if(x>n) return;
    int l = 0,r = 0;
    ull res = 0;
    while(r<x) res+=p[s[r]-'a'],r++;
    if(vis[s[l]-'a'][s[r-1]-'a'].count(res)) mp[s[l]-'a'][s[r-1]-'a'][res]++;
    while(r<n){
        res-=p[s[l]-'a'],l++,res+=p[s[r]-'a'];
        if(vis[s[l]-'a'][s[r]-'a'].count(res)) mp[s[l]-'a'][s[r]-'a'][res]++;
        r++;
    }
}

void init(){
    forn(i,26) forn(j,26) mp[i][j].clear(),vis[i][j].clear();
}

int main(){
	IO;
	p[0] = 1;
	for1(i,26) p[i] = p[i-1]*seed;
	int t;cin>>t;
	while(t--){
		cin>>s;
        init();
        n = s.size();
		int m;cin>>m;
		for1(i,m) {
            cin>>z;
            int len = z.size();
            q[i].len = len;
            q[i].id = i;
            q[i].l = z[0]-'a';
            q[i].r = z[len-1]-'a';
            q[i].has = 0;
            forn(j,len) {
                q[i].has+=p[z[j]-'a'];
                //cerr<<z[j]-'a'<<' '<<p[z[j]-'a']<<"@!#"<<'\n';
            }
            //cerr<<len<<' '<<p[0]<<' '<<q[i].has<<'\n';
            vis[q[i].l][q[i].r][q[i].has] = true;
        }
        sort(q+1,q+m+1,cmp);
        for1(i,m){
           // cerr<<q[i].l<<' '<<q[i].r<<' '<<q[i].has<<'\n';
            if(q[i].len!=q[i-1].len) getans(q[i].len);
            ans[q[i].id] = mp[q[i].l][q[i].r][q[i].has];
        }
        for1(i,m) cout<<ans[i]<<'\n';
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章