有考C语言可信编程认证的同事经常会问到,C语言库没有字符串哈希表操作,那考试遇到了怎么办。虽然历次考试的题目中没有必须要用到C语言哈希表的题目(至少我都能用常规C做出来),但是还需要防患未然,这里给出一道有代表性的题目,可以尝试做做看:https://leetcode-cn.com/problems/substring-with-concatenation-of-all-words/

给定一个字符串 s 和一些长度相同的单词 words。找出 s 中恰好可以由 words 中所有单词串联形成的子串的起始位置。
注意子串要与 words 中的单词完全匹配,中间不能有其他字符,但不需要考虑 words 中单词串联的顺序。

示例:输入:s = "barfoothefoobarman",words = ["foo","bar"]输出:[0,9]解释:从索引 0 和 9 开始的子串分别是 "barfoo" 和 "foobar" 。输出的顺序不重要, [9,0] 也是有效答案。

这题不考虑编程语言的话,用哈希表会比较简单,那要是用C语言的话,可以自己撸个哈希表用,对付这类题目还是绰绰有余的。

思路的话参考https://leetcode-cn.com/problems/substring-with-concatenation-of-all-words/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by-w-6/中的解法二,这里只讲下怎么最简单构造一个哈希表。

首先是选取哈希函数,这里我用的是djb2算法,参考http://www.cse.yorku.ca/~oz/hash.html,碰撞率相当低,分布平衡,实现也很简单,就两三行代码,记住关键数字(5381和33)。

If you just want to have a good hash function, and cannot wait, djb2 is one of the best string hash functions i know. it has excellent distribution and speed on many different sets of keys and table sizes.

Language- 代码


01 unsigned long
02 hash(unsigned char *str)
03 {
04 unsigned long hash = 5381;
05 int c;
06
07 while (c = *str++)
08 hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
09
10 return hash;
11 }

有了字符串哈希函数,就能够将大串字符串转换成数字,数字进而可以作为数组的下标(key)存储信息。那么哈希表的大小怎么取呢?一般大小要大于存储的数据个数,比如最多100个数据,存到哈希表的话大小肯定要大于100才行。对于这题而言,没有明确告诉你单词的最大个数,只能估值了,这里经过几轮提交测试,得到哈希表大小与通过用例个数的关系,说明这道题目最多的单词数可能在300左右,平均个数<50个吧:

5 -> 110/173
10 -> 143/173
50 -> 170/173
100 -> 170/173
300 -> 172/173
400 -> 173/173

这里给出我的解答:

C 代码

01 // 字符串最大值,hash表大小,估值和实际数据个数有关
02 #define MAXWORDCOUNT 1000
03 static int wordCount[MAXWORDCOUNT];
04 static int currWordCount[MAXWORDCOUNT];
05
06 // ref: http://www.cse.yorku.ca/~oz/hash.html
07 unsigned long DJBHash(const char* s, int len) {
08 unsigned long hash = 5381; // 经验值,hash冲突概率低,分布平衡
09 while (len--) {
10 hash = (((hash << 5) + hash) + *(s++)) % MAXWORDCOUNT; /* hash * 33 + c */
11 }
12 return hash;
13 }
14
15 int* findSubstring(char * s, char ** words, int wordsSize, int* returnSize){
16  memset(wordCount, 0, sizeof(wordCount));
17 *returnSize = 0;
18
19 const int kSLen = strlen(s);
20 if (kSLen == 0 || wordsSize == 0) return NULL;
21
22 const int kWordLen = strlen(words[0]);
23 // 将单词数量存到哈希表中,key: word, value: 单词数量
24 for (int i = 0; i < wordsSize; ++i)
25 ++wordCount[DJBHash(words[i], kWordLen)];
26
27 int *result = malloc(sizeof(int) * kSLen);
28 for (int i = 0; i < kWordLen; ++i) {
29 for (int j = i; j + kWordLen * wordsSize <= kSLen; j += kWordLen) {
30 // 统计当前窗口的单词数量
31 for (int k = (j == i ? 0 : wordsSize - 1); k < wordsSize; ++k)
32 ++currWordCount[DJBHash(s + j + k * kWordLen, kWordLen)];
33
34 // 判断两个哈希表是否相等,即窗口中的单词是否和给定词典完全匹配
35 if (memcmp(wordCount, currWordCount, sizeof(wordCount)) == 0)
36 result[(*returnSize)++] = j;
37
38 --currWordCount[DJBHash(s + j, kWordLen)];
39}
40 // 哈希表清零操作
41 memset(currWordCount, 0, sizeof(currWordCount));
42 }
43 return result;
44 }

实操案例:字符串哈希表操作相关推荐

  1. 图解大数据 | Hive搭建与应用@实操案例

    作者:韩信子@ShowMeAI 教程地址:http://www.showmeai.tech/tutorials/84 本文地址:http://www.showmeai.tech/article-det ...

  2. 史上最高效Shell四剑客实操案例

    01.Shell编程四剑客之Find 通过如上基础语法的学习,读者对Shell编程有了更近一步的理解,Shell编程不再是简单命令的堆积,而是演变成了各种特殊的语句.各种语法.编程工具.各种命令的集合 ...

  3. Python自学笔记9:实操案例六(千年虫,购物流程)

    Python自学笔记9:实操案例六(千年虫,购物流程) 网课传送门:第155,156讲,https://www.bilibili.com/video/BV1Sw411Z779?p=155 1.千年虫 ...

  4. Python学习笔记18:实操案例十五(记录用户登录日志,模拟淘宝客服自动回复)

    Python学习笔记18:实操案例十五(记录用户登录日志,模拟淘宝客服自动回复) 网课传送门:https://www.bilibili.com/video/BV1Sw411Z779?p=168& ...

  5. Python自学笔记6:实操案例三(十进制转换二、八、十六进制),手机充值,计算能量消耗,预测未来子女身高

    Python自学笔记6:实操案例三(十进制转换二.八.十六进制),手机充值,计算能量消耗,预测未来子女身高 杨淑娟老师网课传送门(非广告):https://www.bilibili.com/video ...

  6. Python自学笔记10:实操案例七(根据星座测试性格特点、模拟12306火车订票下单)

    Python自学笔记10:实操案例七(根据星座测试性格特点.模拟12306火车订票下单) 网课传送门:https://www.bilibili.com/video/BV1Sw411Z779?p=157 ...

  7. Python学习笔记7:实操案例四(支付密码的验证,模拟QQ账号登录,商品价格竞猜,星座看运势)

    Python学习笔记7:实操案例四(支付密码的验证,模拟QQ账号登录,商品价格竞猜,星座看运势) 1.支付密码的验证: 这个主要就是调用isdigit()函数判断字符串是不是全是数字组成. pwd=i ...

  8. 实操案例:机智云调试APP控制云端虚拟设备

    本文通过<机智云调试APP控制云端虚拟设备>实操案例,快速理解和体验机智云接入服务,完成新手入门. 机智云自助开发平台 机智云自助开发平台提供一套模拟软件开发工具,其中包括虚拟设备和机智云 ...

  9. 图解大数据 | 应用Map-Reduce进行大数据统计@实操案例

    作者:韩信子@ShowMeAI 教程地址:http://www.showmeai.tech/tutorials/84 本文地址:http://www.showmeai.tech/article-det ...

最新文章

  1. MQTT 协议 Client ID 长度不能超过23个字符
  2. opencv中的Rodrigues()函数
  3. java弹出窗放textarea_java中窗体上有一个Button和一个TextArea当鼠标经过按钮上的某一点时在文本框中输出该点的坐标事件...
  4. gdb条件断点的值一定会断吗_GDB:如果变量等于值则中断
  5. linux内核启动后门,Linux下编写隐蔽的自启动回连后门
  6. Spring MVC集成Log4j
  7. 从头编写 asp.net core 2.0 web api 基础框架 (4) EF配置
  8. sqldeveloper的查看执行计划快捷键F10
  9. Linux 下 -bash: mysql: command not found解决办法
  10. Java ——异常处理
  11. android activity 通知 service,android activity和service通信问题
  12. bilstmcrf词性标注_BiLSTM+CRF 的实现详解
  13. 数据拟合MATLAB与origin哪个好,Origin:数据处理、作图和拟合的利器
  14. Linux虚拟机获取最高权限
  15. 重复在学习中的重要性
  16. matlab连通区域质心标记,连通域的质心
  17. mysql 索引配置_Mysql索引配置
  18. Android集成百度人脸识别(一)基础版SDK
  19. java抢购_java redis 实现抢购秒杀
  20. 武汉光庭总经理苏晓聪:智能网联控制器实践与创新

热门文章

  1. Bootstrap 流式布局
  2. String.raw()方法
  3. 视觉SLAM笔记(18) Sophus
  4. 三星s8android pie,三星更改Galaxy S8的Android Pie更新计划,添加Gala
  5. python每日一题今天的答案_python每日一题总结1
  6. php如何处理查询请求,PHP如何处理Web请求流程
  7. 软件版本号命名规范_如何才能给文件合理命名,提高工作效率?我有3个建议!...
  8. lisp如何将度分秒转换为弧度_重磅干货!如何利用Stata进行空间冷热点分析 | 社论前沿...
  9. mongodb-java-driver基本用法
  10. ExtJs六(ExtJs Mvc首页展示)