题目描述

人们在英文字典中查找某个单词的时候可能不知道该单词的完整拼法,而只知道该单词的一个错误的近似拼法,这时人们可能陷入困境,为了查找一个单词而浪费大量的时间。带有模糊查询功能的电子字典能够从一定程度上解决这一问题:用户只要输入一个字符串,电子字典就返回与该单词编辑距离最小的几个单词供用户选择。

字符串a与字符串b的编辑距离是指:允许对a或b串进行下列“编辑”操作,将a变为b或b变为a,最少“编辑”次数即为距离。

  1. 删除串中某个位置的字母;
  2. 添加一个字母到串中某个位置;
  3. 替换串中某一位置的一个字母为另一个字母;

JSOI团队正在开发一款电子字典,你需要帮助团队实现一个用于模糊查询功能的计数部件:对于一个待查询字符串,如果它是单词,则返回-1;如果它不是单词,则返回字典中有多少个单词与它的编辑距离为1。

输入输出格式

输入格式:

第一行包含两个正整数N (N ≤ 10,000)和M (M ≤ 10,000)。

接下来的N行,每行一个字符串,第i + 1行为单词Wi。单词长度在1至20之间。

再接下来M行,每行一个字符串,第i + N + 1表示一个待查字符串Qi。待查字符串长度在1至20之间。Wi和Qi均由小写字母构成,文件中不包含多余空格。所有单词互不相同,但是查询字符串可能有重复。

输出格式:

输出应包括M行,第i行为一个整数Xi。Xi = -1表示Qi为字典中的单词;否则Xi表示与Qi编辑距离为1的单词的个数。


emmmmm, 据说是trie树, 不是很会呀, 勉强用hash搞一下吧; 首先存下每个单词的hash值, 排序是为了以后的查找。 依次读入每一个单词, 再用前缀和后缀和记录hash值,用二分查找是否存在, 存在即返回, 依次如题目所示枚举删除、添加、替换的点, 找到即ans++, 其中一些情况不必再次查找, 如类似aab的情况,删去两个a的效果是一样;最后输出即可;

  1. #include <bits/stdc++.h>
  2.  
  3. using namespace std;
  4.  
  5. typedef long long ll;
  6. typedef unsigned long long ull;
  7. const int INF = 0x3f3f3f3f;
  8. const int MAXN = 1e5 + ;
  9. const int MAXM = 3e3 + ;
  10.  
  11. template < typename T > inline void read(T &x) {
  12. x = ; T ff = , ch = getchar();
  13. while(!isdigit(ch)) {
  14. if(ch == '-') ff = -;
  15. ch = getchar();
  16. }
  17. while(isdigit(ch)) {
  18. x = (x << ) + (x << ) + (ch ^ );
  19. ch = getchar();
  20. }
  21. x *= ff;
  22. }
  23.  
  24. template < typename T > inline void write(T x) {
  25. if(x < ) putchar('-'), x = -x;
  26. if(x > ) write(x / );
  27. putchar(x % + '');
  28. }
  29.  
  30. int n, m;
  31. ull h[MAXN], p[], s1[], s2[];
  32. char s[];
  33.  
  34. inline bool find(ull x) {
  35. int l = , r = n;
  36. while(l < r) {
  37. int mid = ((l + r) >> );
  38. if(h[mid] >= x) r = mid;
  39. else l = mid + ;
  40. }
  41. return h[l] == x;
  42. }
  43.  
  44. int main() {
  45. read(n); read(m);
  46.  
  47. p[] = ;
  48. for(register int i = ; i <= ; ++i)
  49. p[i] = p[i - ] * ;
  50. for(register int i = ; i <= n; ++i) {
  51. scanf("%s", s + );
  52. int len = strlen(s + );
  53. for(register int j = ; j <= len; ++j)
  54. h[i] = h[i] * + (s[j] - 'a' + );
  55. }
  56.  
  57. sort(h + , h + n + );
  58.  
  59. while(m--) {
  60. scanf("%s", s + );
  61. int len = strlen(s + ), ans = ;
  62. s2[len + ] = ;
  63. for(register int i = ; i <= len; ++i)
  64. s1[i] = s1[i - ] * + (s[i] - 'a' + );
  65.  
  66. if(find(s1[len])) {
  67. write(-);
  68. putchar('\n');
  69. continue;
  70. }
  71. for(register int i = len; i >= ; --i)
  72. s2[i] = s2[i + ] + (s[i] - 'a' + ) * p[len - i];
  73.  
  74. for(register int i = ; i < len; ++i)
  75. if(s[i] != s[i + ])
  76. if(find(s1[i] * p[len - i - ] + s2[i + ])) ++ans;
  77.  
  78. //删除
  79.  
  80. for(register int i = ; i <= len; ++i)
  81. for(register int j = ; j <= ; ++j)
  82. if(j != (s[i] - 'a' + ))
  83. if(find(s1[i] * p[len - i + ] + j * p[len - i] + s2[i + ])) ++ans;
  84.  
  85. //添加
  86.  
  87. for(register int i = ; i <= len; ++i)
  88. for(register int j = ; j <= ; ++j)
  89. if(j != (s[i] - 'a' + ))
  90. if(find(s1[len] + (j - (s[i] - 'a' + )) * p[len - i])) ++ans;
  91.  
  92. //替换
  93.  
  94. printf("%d\n", ans);
  95.  
  96. }
  97. return ;
  98. }

洛谷P4407 [JSOI2009]电子字典的更多相关文章

  1. P4407 [JSOI2009]电子字典

    传送门 我的哈希打挂了--然而大佬似乎用哈希可以过还跑得很快-- 删除,枚举删哪个字符,记删之后的哈希值存map 插入,相当于在单词里删字符,去对应的map里查找 更改,相当于两个都删掉同一个位置的字 ...

  2. [JSOI2009]电子字典 hash

    题面:洛谷 题解: 做法....非常暴力. 因为要求的编辑距离最多只有1,所以我们直接枚举对那个位置(字符)进行操作,进行什么样的操作,加入/修改/删除哪个字符,然后暴力枚举hash判断即可, #in ...

  3. 洛谷4054 [JSOI2009]计数问题

    原题链接 二维树状数组模板题. 对每一种颜色开一棵二维树状数组统计即可. #include<cstdio> using namespace std; const int N = 310; ...

  4. 洛谷P4054 [JSOI2009]计数问题(二维树状数组)

    题意 题目链接 Sol 很傻x的题.. c才100, n, m才300,直接开100个二维树状数组就做完了.. #include<bits/stdc++.h> using namespac ...

  5. luogu4407 [JSOI2009]电子字典 字符串hash + hash表

    暴力枚举,然后\(hash\)表判断 复杂度\(O(26 * 20 * n)\) 具体而言 对于操作1:暴力枚举删除 对于操作2:暴力添加,注意添加不要重复 对于操作3:暴力替换,同样的注意不要重复 ...

  6. 洛谷 P4307 [JSOI2009]球队收益 / 球队预算(最小费用最大流)

    题面 luogu 题解 最小费用最大流 先假设剩下\(m\)场比赛,双方全输. 考虑\(i\)赢一局的贡献 \(C_i*(a_i+1)^2+D_i*(b_i-1)^2-C_i*a_i^2-D_i*b_ ...

  7. 洛谷$P4045\ [JSOI2009]$密码 $dp$+$AC$自动机

    正解:$dp$+$AC$自动机+搜索 解题报告: 传送门$QwQ$ 首先显然先建个$AC$自动机,然后考虑设$f_{i,j,k}$表示长度为$i$,现在在$AC$自动机的第$j$个位置,已经表示出来的 ...

  8. [洛谷P2580]于是他错误的点名开始了

    洛谷P2580的一个水题,用啥都能过,不过为了练习一下刚刚学会的字典树,还是认真做一下吧. #include <cstdio> #include <cstring> using ...

  9. 洛谷 P1219 八皇后【经典DFS,温习搜索】

    P1219 八皇后 题目描述 检查一个如下的6 x 6的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行.每列有且只有一个,每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子. 上面的布局可以用序 ...

随机推荐

  1. 使用valgrind进行内存泄漏和非法内存操作检测

    valgrind是一个强大的工具,最常用的功能是用它来检测内存泄漏和非法内存的使用.要想让valgrind报告的更加细致,请使用-g进行编译. 基本命令如下: $ valgrind --tool=me ...

  2. java数据的5种存储位置(转)

    任何语言所编写的程序,其中的各类型的数据都需要一个存储位置,java中书的存储位置分为以下5种: 1.寄存器 最快的存储区,位于处理器内部,但是数量及其有限.所以寄存器根据需求自动分配,无序人为控制. ...

  3. hdu 6121 Build a tree

    /** * 题意:一棵 n 个点的完全 k 叉树,结点标号从 0 到 n - 1,求以每一棵子树的大小的异或和. * 解法:k叉树,当k=1时,特判,用xorn函数,具体解释:http://blog. ...

  4. 【译】在ES6中如何优雅的使用Arguments和Parameters

    原文地址:how-to-use-arguments-and-parameters-in-ecmascript-6 ES6是最新版本的ECMAScript标准,而且显著的改善了JS里的参数处理.我们现在 ...

  5. 《java编程思想》:设计模式(不定期更新)

    1.策略设计模式 创建一个能够根据所传递的参数对象的不同而具有不同的方法,被称为策略设计模式.这类方法包含索要执行的算法中固定不变的部分,而“策略”包含变化的部分.策略就是传递进去的参数对象.在下面的 ...

  6. aoj 0118 Property Distribution

    タナカ氏が HW アールの果樹園を残して亡くなりました.果樹園は東西南北方向に H × W の区画に分けられ.区画ごとにリンゴ.カキ.ミカンが植えられています.タナカ氏はこんな遺言を残していました. ...

  7. java自定义类型 作为HashMap中的Key值 (Pair<V,K>为例)

    由于是自定义类型,所以HashMap中的equals()方法和hashCode()方法都需要自定义覆盖. 不然内容相同的对象对应的hashCode会不同,无法发挥算法的正常功能,覆盖equals方法, ...

  8. ACM学习历程——POJ 1700 Crossing River(贪心)

    Description A group of N people wishes to go across a river with only one boat, which can at most ca ...

  9. 使用Tornado作为Django App的服务器

    闲来无事,折腾折腾. 老是听说tonado是个异步web框架和服务器,作为框架倒是了解到了,但是服务器一直不太懂.所以决定了解一下,既然可以做服务器,那就把自己的django app部署到这上边去. ...

  10. python爬虫知识点总结(一)库的安装

    环境要求: 1.编程语言版本python3: 2.系统:win10; 3.浏览器:Chrome68.0.3440.75:(如果不是最新版有可能影响到程序执行) 4.chromedriver2.41 注 ...