EOJ 3502 密码碰撞

题目已经给出了提示,用哈希求解。

解题思路就是枚举每个字符串的的子串,计算其哈希值,存在set中(去重),然后再将各个哈希值的出现次数存储在map中。

最后,遍历map,并累计。最后的结果应减去cas数,即减去自己对自己的密码。

#include <bits/stdc++.h>

typedef long long int ll;

#define PI 3.14159265358979323846
#define INF 0x3f3f3f3f
#define INFLL 0x3f3f3f3f3f3f3f3fll
#define maxn 1000+10
#define mod 2000120420010122

using namespace std;


inline ll getHash(string s){//网上学习的哈希函数,听说这个函数的分布比较均匀,get
    ll hash=0;
    for(int i=0;i<s.length();i++){
        hash=s[i] + (hash<<6) + (hash<<16) - hash;
    }
    return hash;
}

void solve(){
    int cas;
    cin>>cas;
    string password[cas];
    for(int i=0;i<cas;i++){
        cin>>password[i];
    }
    map<ll,ll> ma;
    for(int i=0;i<cas;i++){
        set<ll> se;
        int len=(int)password[i].length();
        string affect=password[i];
        for(int l=1;l<=len;l++){
            for(int j=0;j<len-l+1;j++){
                string tmp="";
                for(int k=0;k<l;k++){
                    tmp+=affect[j+k];
                }
                ll hash=getHash(tmp);
                se.insert(hash);
            }
        }
        for(ll hash : se){
            ma[hash]++;
        }
    }
    ll cnt=0;
    for(int i=0;i<cas;i++){
        cnt += ma[getHash(password[i])];
    }
    cout<<cnt - cas<<endl;
}

int main(int argc, char const *argv[]){
    solve();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/J__Max/article/details/80321681