PTA 字符串关键字的散列映射(25 分)

7-17 字符串关键字的散列映射(25 分)

给定一系列由大写英文字母组成的字符串关键字和素数P,用移位法定义的散列函数H(Key)将关键字Key中的最后3个字符映射为整数,每个字符占5位;再用除留余数法将整数映射到长度为P的散列表中。例如将字符串AZDEG插入长度为1009的散列表中,我们首先将26个大写英文字母顺序映射到整数0~25;再通过移位将其映射为3×32?2??+4×32+6=3206;然后根据表长得到,即是该字符串的散列映射位置。

发生冲突时请用平方探测法解决。

输入格式:

输入第一行首先给出两个正整数N(≤500)和P(≥2N的最小素数),分别为待插入的关键字总数、以及散列表的长度。第二行给出N个字符串关键字,每个长度不超过8位,其间以空格分隔。

输出格式:

在一行内输出每个字符串关键字在散列表中的位置。数字间以空格分隔,但行末尾不得有多余空格。

输入样例1:

4 11
HELLO ANNK ZOE LOLI

输出样例1:

3 10 4 0

输入样例2:

6 11
LLO ANNA NNK ZOJ INNK AAA

输出样例2:

3 0 10 9 6 1
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int n,cap;
const int maxn = 50100;
int Hashvis[maxn];
int ans[maxn];
set<string> same;
map<string,int> maps;
int GetHash(string t)
{
    int ans = 0;
    for(int i=0;i<min((int)t.length(),3);i++)
    {
        ans+=((int)pow(32,i)*((int)(t[i]-‘A‘)));
    }
    int tans = ans;
    ans%=cap;
    int k = 1;
    while(Hashvis[ans]) //平方探测法
    {
        ans = (tans + k*k)%cap;
        if(!Hashvis[ans]) break;
        ans = (tans - k*k + cap)%cap;
        k++;
    }
    Hashvis[ans] = 1;
    return ans;
}
int main()
{
    memset(ans,0,sizeof(ans));
    memset(Hashvis,0,sizeof(Hashvis));
    scanf("%d%d",&n,&cap);
    string s;
    for(int i=0;i<n;i++)
    {
        cin>>s;
        reverse(s.begin(),s.end());
        if(same.count(s)) ans[i] = maps[s]; //相同判断
        else{
        same.insert(s);
        ans[i] = GetHash(s);
        maps[s] = ans[i];
        }
    }
    for(int i=0;i<n;i++)
        printf("%d%c",ans[i],i==n-1?‘\n‘:‘ ‘);
}

  


代码里有两处需要注意的地方,一个是用set的重复判断,还有平方探测法;

原文地址:https://www.cnblogs.com/masterchd/p/8127811.html

时间: 2024-10-08 02:17:42

PTA 字符串关键字的散列映射(25 分)的相关文章

PTA数据结构与算法题目集(中文) 7-43字符串关键字的散列映射 (25 分)

PTA数据结构与算法题目集(中文)  7-43字符串关键字的散列映射 (25 分) 7-43 字符串关键字的散列映射 (25 分) 给定一系列由大写英文字母组成的字符串关键字和素数P,用移位法定义的散列函数(将关键字Key中的最后3个字符映射为整数,每个字符占5位:再用除留余数法将整数映射到长度为P的散列表中.例如将字符串AZDEG插入长度为1009的散列表中,我们首先将26个大写英文字母顺序映射到整数0~25:再通过移位将其映射为3:然后根据表长得到,即是该字符串的散列映射位置. 发生冲突时请

案例5-1.3 整型关键字的散列映射 (25分)--散列表(除留余数法+线性探测法)

解题思路: 1.初始化散列表,用于标记散列地址是否已用 2.构造结构体,(关键字去重)记录关键字的值和地址 3.读入数据,判断该关键字是否重复查询 4.用辅助数组记录每个关键字的地址,遍历输出 #include <stdio.h> #include <string.h> typedef struct { int key; int value; } Hash; int main() { int n,p; scanf("%d %d",&n,&p);

栈,散列映射

栈的方法 public void push(E item) public E pop() public boolean empty() public E peek()//获得栈顶数据 public int search(Oject data)//查找栈是否有data项,没有返回-1 HashMap散列映射 HashMap<String,V> 方法 public void put(Key k,Value v)//加入 public void clear()//清空散列映射 public bool

java 散列与散列码探讨 ,简单HashMap实现散列映射表运行各种操作示列

package org.rui.collection2.maps; /** * 散列与散列码 * 将土拔鼠对象与预报对象联系起来, * @author lenovo * */ //土拨鼠 public class Groundhog { protected int number; public Groundhog(int n) { number=n; } @Override public String toString() { return "Groundhog #" + number

java 散列与散列码探讨 ,简单HashMap实现散列映射表执行各种操作示列

package org.rui.collection2.maps; /** * 散列与散列码 * 将土拔鼠对象与预报对象联系起来, * @author lenovo * */ //土拨鼠 public class Groundhog { protected int number; public Groundhog(int n) { number=n; } @Override public String toString() { return "Groundhog #" + number

进阶实验8-2.1 逆散列问题 (30分)

给定长度为 N 的散列表,处理整数最常用的散列映射是 (.如果我们决定用线性探测解决冲突问题,则给定一个顺序输入的整数序列后,我们可以很容易得到这些整数在散列表中的分布.例如我们将 1.2.3 顺序插入长度为 3 的散列表HT[]后,将得到HT[0]=3,HT[1]=1,HT[2]=2的结果. 但是现在要求解决的是“逆散列问题”,即给定整数在散列表中的分布,问这些整数是按什么顺序插入的? 输入格式: 输入的第一行是正整数 N(≤1000),为散列表的长度.第二行给出了 N 个整数,其间用空格分隔

Redis常用命令(一) 字符串键、散列键

redis是key-value的数据结构,每条数据都是一个键值对 键的类型是字符串,因为默认是字符串所以都不用加引号 注意:键不能重复 值的类型分为五种: 字符串string 散列hash 列表list 集合set 有序集合zset string字符串键 set key value  # 设置的键不存在则为添加,如果设置的键已经存在则修改 set name daiby set key value [NX|XX]  # NX: 如果key不存在则成功,反之失败(不覆盖旧值)! XX: 如果key存

C++学习笔记 &lt;hash_map&gt; &lt;散列映射&gt;

对于大型容器而言hash_map要比map快5至10倍的元素查找速度. map对其元素类型要求有一个<,hash_map要求一个==和一个散列函数. map<string,int>  m1;   //用<比较串 map<string,int Nocase>   m2;       //用Nocase()比较串 hash_map<string,int>   hm1;        //用Hash<string>()散列,用==比较 hash_map

弱散列映射WeakHashMap

WeakHashMap解决了什么问题? 设计WeakHashMap类是为了解决一个有趣的问题.如果有一个值,对应的键已经不再使用了,将会出现什么情况呢?假定对某个键的最后一次引用已经消亡,不再有任何途径引用这个值的对象了.但是,由于在程序中的任何部分没有再出现这个键,所以,这个键/值对无法从映射中删除.为什么垃圾回收器不能够删除它呢?难道删除无用的对象不是垃圾回收器的工作吗? 遗憾的是,事情没有这样简单.垃圾回收器跟踪活动的对象.只要映射对象是活动的,其中的所有桶也是活动的,它们不能被回收.因此