2020牛客寒假算法基础集训营5 H Hash


哈希函数把一个只由小写字符组成的字符串转化成了一个26进制的数,不取模的情况下,任意小写字符串和自然数是一一对应的。因此,只要把给的字符串转换成对应的26进制整数,加上模数后转换回字符串,一定可以得到一个最小字典序大于原串的字符串。只要这个新字符串长度为6即是满足要求的字符串。

加mod还不行 说明越zzzzzz的界了 即长度大于6 加k*mod就更不行了
mod比最大hash值266-1小 所以有可能加上mod后还在长度为6的字符串hash值范围内
#include<bits/stdc++.h>
using namespace std;
char s[10],t[10];

int main(){
    int mod;
    while(~scanf("%s",s)){
        scanf("%d",&mod);
        int has=0;
        for(int i=0;i<6;i++)has=has*26+s[i]-'a';
        has+=mod;
        for(int i=5;i>=0;i--){
            s[i]=has%26+97;
            has/=26;
        }
        s[6]=0;
        if(has)cout<<-1<<endl;
        else cout<<s<<endl;
    }
}

刚开始写的搜索 由于多组数据(1000组)妥妥的T 

后来想到大于s且取模后hash值等于s的字符串原hash值为hash(s)+k*mod

只需预处理出所有长度为6的字符串的hash值

但3e8预处理还是T了 

虽然k从小到大枚举,第一个满足条件的字符串显然字典序最小

由于预处理超时就没继续想下去了 枚举之后只需判断是否在长度为6的字符串的hash值范围内

那么mod不行,即超出了长度为6的字符串hash值范围  k*mod显然也不行

字符串在26进制下,比较字典序大小等价于比较对应的26进制大小。加mod,取模结果不变同时字典序最小

#include<bits/stdc++.h>
using namespace std;
 
char s[10],tmp[10];
int mod,flag,ans=0;
int has(char* s){
    int res=0;
    for(int i=0;i<6;i++)
     res=(1ll*res*26+s[i]-'a')%mod;
    return res;
 
}
void dfs(int step){
    if(flag)return;
    if(step==6){
        if(has(tmp)==ans){
            flag=1;
            for(int i=0;i<6;i++)putchar(tmp[i]);
            return;    
        }
        return ;
    }
    for(char i='a';i<='z';i++){
        if(flag)return;
        tmp[step]=i;
        dfs(step+1);
    }
}
int main(){
    while(~scanf("%s",s)){
        scanf("%d",&mod);
        ans=has(s);
        //cout<<ans<<endl;
        flag=0;
        for(int i=5;i>=0;i--){
            if(flag)break;
            strncpy(tmp,s,i);
            for(char j=s[i]+1;j<='z';j++){
                if(flag)break;
                tmp[i]=j;
                dfs(i+1);
            }
        }
        if(!flag)cout<<-1<<endl;
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/wyh447154317/p/12309397.html