Codeforces-963 D Frequency of String

题意:给你一个字符串,进行q次询问操作,每次给你一个n和一个子串,问能否在字符串中出现n次子串,若可以输出最短长度的n次子串,否则输出-1

题解:优雅的暴力哈希,枚举每一个不同种长度的子串,注意是不同种!因为这样子能减少枚举的次数,这是一个巨大的优化,同时用unordered_map这个不按key排序的map,减少logn的STL复杂度。(我就说一定存在不按照key排序的map啊啊啊)

还是我很挫的代码

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <map>
#include <unordered_map>
#include <queue>
#include <vector>
#include <cstring>
#include <iomanip>
#include <set>
#include<ctime>
//CLOCKS_PER_SEC
#define se second
#define fi first
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define Pii pair<int,int>
#define Pli pair<ll,int>
#define ull unsigned long long
#define pb push_back
#define fio ios::sync_with_stdio(false);cin.tie(0)
const int N=1e5+5;
const ull base=131;
const int INF=0x3f3f3f3f;
using namespace std;
ull Hash[N];
ull p[N];
unordered_map<ull,int>mp;
ull get(int l,int r){
    if(l==0)return Hash[r];
    return Hash[r]-Hash[l-1]*p[r-l+1];
}
int L[N],id[N],a[N];
ull H[N];
bool cmp(int x,int y){
    return L[x]<L[y];
}
vector<int>ans[N];
int main(){
    fio;
    string str;
    cin>>str;
    int len=str.length();
    Hash[0]=str[0];
    p[0]=1;
    for(int i=1;i<len;i++){
        Hash[i]=Hash[i-1]*base+str[i];
        p[i]=p[i-1]*base;
    }
    int n;
    cin>>n;
    for(int i=1;i<=n;i++){
        string op;
        cin>>a[i];
        cin>>op;
        id[i]=i,L[i]=op.length();
        ull u=0;
        for(int j=0;j<L[i];j++){
            u=u*base+op[j];
        }
        H[i]=u;
        mp[H[i]]=i;
    }
    sort(id+1,id+1+n,cmp);
    for(int i=1,oo=1;i<=n;i+=oo){
        oo=1;
        while(L[id[oo+i]]==L[id[i]])oo++;
        int pp=id[i];
        for(int j=0;j+L[pp]<=len;j++){
            ull m=get(j,j+L[pp]-1);
            if(mp.find(m)!=mp.end()){
                ans[mp[m]].pb(j);
            }
        }
    }
    for(int i=1;i<=n;i++){
        if(ans[i].size()<a[i])cout<<-1<<endl;
        else{
            int MIN=INF;
            for(int j=a[i]-1;j<ans[i].size();j++){
                MIN=min(MIN,ans[i][j]-ans[i][j-a[i]+1]+L[i]);
            }
            cout<<MIN<<endl;
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/Mrleon/p/8886982.html