作为哈佛大学CS50课程的一项任务,学生的任务是创建一个拼写检查程序.任务的主要目标是速度 – 纯粹的速度 – 我已经达到了我打败员工实施的程度,但我觉得我可以做得更好,并且正在寻找正确方向的推动力.

这是我的伪代码:

// read the dictionary word list
Read entire dictionary in one fread into memory
rawmemchr through and pick out the words
send each word through the hash function
create chain links for any index where collisions occur

// accept the incoming test words
Run the test word through the hash function
compare to the existing table / linked list
return the result of the comparison

使用150K字的字典,输入文本高达6MB,我能够准确地拼写检查大约半秒钟.

但是,当我查看来自输入文本的单词时,很明显这些单词的大部分是常见的(如“the”,“and”,“for”),以及大多数拼写错误的单词也会多次检查.

我的直觉说我应该能够“缓存”“好点击”和“糟糕点击”,这样我就不会一遍又一遍地为表格查找扫描相同的单词.即使当前结果非常接近O(1),我觉得我应该能够通过重新评估我的方法来减少几微秒的时间.

例如,在我加载字典后,文本输入可能只有8MB,但是:“误导”.因此,我不想反复哈希/检查相同的单词(以计算费用),我想了解是否有一种方法可以编程方式丢弃已经被散列和拒绝的单词,但是以一种比哈希/检查本身. (我正在使用MurmurHash3,fwiw).

我意识到理论性能改进将局限于输入文本很长的情况,并且存在大量重复拼写错误.基于我评估的一些输入文本,以下是一些结果:

Unique Misspellings: 6960
Total Misspellings:  17845
Words in dictionary: 143091
Words in input text: 1150970
Total Time:          0.56 seconds

Unique Misspellings: 8348
Total Misspellings:  45691
Words in dictionary: 143091
Words in input text: 904612
Total Time:          0.83 seconds

在第二个示例运行中,您可以看到我必须为每个拼写错误的单词返回哈希表大约5.5次!这对我来说似乎很难解决,我觉得必须有一种更有效的方法来解决这种情况,因为我的程序的大部分时间都花在了哈希函数上.

我可以实现Posix线程(这在8核系统上运行)来改善程序的时间,但我更感兴趣的是改进我的方法和思考过程.

对不起,这是漫长的啰嗦,但这是我的第一个Stack Overflow帖子,我正在努力做到彻底.我在发布之前进行了搜索,但大多数其他“拼写检查”帖子与“如何”而不是“改进”相关.我很感激能够让我指出正确方向的建议.

http://github.com/Ganellon/spell_check

解决方法

这是一个很好解决的问题. ;-)你应该研究一个名为 trie的数据结构.特里是一个由单个字符构成的树,因此路径代表信息.每个节点都包含可以合法添加到当前前缀的字母.当字母是有效字时,也会记录.

四个字:

root-> [a]-> [a]-> [r]-> [d]-> [v]-> [a]-> [r]-> [k*]->[s*]
             [b]
                \> [a]-> [c]-> [i*]
                               [u]-> [s*]

这将代表“aardvark”,“aardvarks”,“abaci”和“abacus”.节点是垂直连续的,因此第二个字母[ab]是一个节点,第五个字母[i * u]是一个节点.

逐个字符遍历特里字符,并在您触及空格时检查有效字.如果你不能用你所拥有的角色进行遍历,那么这就是一个坏词.如果你在击中太空时找不到有效的东西,这是一个坏词.

这是O(n)处理(n =字长),它非常非常快.构建trie将占用大量内存,但你不关心我的想法.

如何在C程序中提高拼写检查时间?的更多相关文章

  1. 如何在Swift中获取文本中真实单词的数量

    参见英文答案>NumberofwordsinaSwiftStringforwordcountcalculation4个编辑:已经存在类似于此问题的问题,但它是由特定字符分隔的数字(Getno.Ofwordsinswiftforaveragecalculator).相反,这个问题是要获得文本中真实单词的数量,以各种方式分开:换行符,一些换行符,一个空格,一个空格等.我想用Swift3获取字符串中的单

  2. android – 突出显示通过EditText搜索的所有单词

    您好,我想知道如何突出显示在EditText中输入的所有单词,并将出现在TextView中此帖子与此相关HighlightTextviewUsingEditText解决方法Sayet是您的EditText,电视是TextView对象.使用以下代码:结果是:

  3. Android Tamil字体之间的英文单词

    我有一个TextView有一个巨大的文本之间,我有一个tamil字,我知道如何嵌入tamil字体在单独的文本视图.但我需要英文单词之间的tamil单词请提前感谢我在textview中的部分文字:Seasonalmessageslikewelcome()isusedinKolam.VolunteeringtodrawkolamattempleissometimesdonewhenadeVotee’s

  4. 在JavaScript中查找字符串中最长单词的三种方法(推荐)

    这篇文章主要介绍了在JavaScript中查找字符串中最长单词的三种方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  5. php – strpos用两个单词来查找

    我在stackoverflow上找到了这个例子:但是如何让它搜索两个单词.我需要这样的东西:如果$a包含单词“are”或“be”或者两者都包含echo“contains”;我试过xor和||只需单独检查两个单词并使用boolean或-运算符检查$a中是否包含其中一个或两个:请注意,由于or-operator,如果第一个已经显示$a包含’are’,则不执行第二次检查.

  6. PHP字符串/文字处理问题

    可以说我有以下句子:但是我有一个限制,那句话只允许25个字符.这可能会让我有类似的东西:然而,这句话没有任何语法意义,所以我宁愿找到我们可以允许的最后一个词,同时保持25个字符限制.这会给我们这样的东西:这将低于25个字符限制,但它具有更多的语法意义.即单词没有被分解,我们在保持极限的同时拥有最多可理解单词.如何编写一个将接受字符串的函数和一个char限制(如25),如果字符串超出限制,则返回具有最大字数的字符串?

  7. php – 正则表达式匹配一定长度的ALL-CAPS单词

    我有一个函数可以修复那些坚持让一切都变得更好的顽皮用户的资本化!我希望只在字符串包含3个或更多大写字母的大写单词时才调用我的函数.这可以用正则表达式完成吗?

  8. 用于计算各种语言中的单词的PHP库/类?

    是否有任何特定的字符或一组字符?我记得阅读有关在T9写作中识别日语单词有多困难的东西,但是找不到它.以下内容应正确返回使用空格或标点符号作为单词分隔符的语言的单词数:

  9. php – mysql FULLTEXT搜索多个单词

    我从来没有听过这个直接的答案,我只需要FULLTEXT搜索几个字,多个字“FirstnameLastname”但是如果我在这里输入多个单词,则无法运行查询.如果你想做精确的搜索:

  10. 正则表达式 – 提取|之间的最后一个单词|

    我有以下数据集我想提取||之间的最后一个字作为一个新的变量即我试过用我们可以用数据

随机推荐

  1. 从C到C#的zlib(如何将byte []转换为流并将流转换为byte [])

    我的任务是使用zlib解压缩数据包(已接收),然后使用算法从数据中生成图片好消息是我在C中有代码,但任务是在C#中完成C我正在尝试使用zlib.NET,但所有演示都有该代码进行解压缩(C#)我的问题:我不想在解压缩后保存文件,因为我必须使用C代码中显示的算法.如何将byte[]数组转换为类似于C#zlib代码中的流来解压缩数据然后如何将流转换回字节数组?

  2. 为什么C标准使用不确定的变量未定义?

    垃圾价值存储在哪里,为什么目的?解决方法由于效率原因,C选择不将变量初始化为某些自动值.为了初始化这些数据,必须添加指令.以下是一个例子:产生:虽然这段代码:产生:你可以看到,一个完整的额外的指令用来移动1到x.这对于嵌入式系统来说至关重要.

  3. 如何使用命名管道从c调用WCF方法?

    更新:通过协议here,我无法弄清楚未知的信封记录.我在网上找不到任何例子.原版的:我有以下WCF服务我输出添加5行,所以我知道服务器是否处理了请求与否.我有一个.NET客户端,我曾经测试这一切,一切正常工作预期.现在我想为这个做一个非托管的C客户端.我想出了如何得到管道的名称,并写信给它.我从here下载了协议我可以写信给管道,但我看不懂.每当我尝试读取它,我得到一个ERROR_broKEN_P

  4. “这”是否保证指向C中的对象的开始?

    我想使用fwrite将一个对象写入顺序文件.班级就像当我将一个对象写入文件时.我正在游荡,我可以使用fwrite(this,sizeof(int),2,fo)写入前两个整数.问题是:这是否保证指向对象数据的开始,即使对象的最开始可能存在虚拟表.所以上面的操作是安全的.解决方法这提供了对象的地址,这不一定是第一个成员的地址.唯一的例外是所谓的标准布局类型.从C11标准:(9.2/20)Apointe

  5. c – 编译单元之间共享的全局const对象

    当我声明并初始化一个const对象时.两个cpp文件包含此标头.和当我构建解决方案时,没有链接错误,你会得到什么如果g_Const是一个非const基本类型!PrintInUnit1()和PrintInUnit2()表明在两个编译单元中有两个独立的“g_Const”具有不同的地址,为什么?

  6. 什么是C名称查找在这里? (&GCC对吗?)

    为什么在第三个变体找到func,但是在实例化的时候,原始变体中不合格查找找不到func?解决方法一般规则是,任何不在模板定义上下文中的内容只能通过ADL来获取.换句话说,正常的不合格查找仅在模板定义上下文中执行.因为在定义中间语句时没有声明func,并且func不在与ns::type相关联的命名空间中,所以代码形式不正确.

  7. c – 在输出参数中使用auto

    有没有办法在这种情况下使用auto关键字:当然,不可能知道什么类型的.因此,解决方案应该是以某种方式将它们合并为一个句子.这可用吗?解决方法看起来您希望默认初始化给定函数期望作为参数的类型的对象.您无法使用auto执行此操作,但您可以编写一个特征来提取函数所需的类型,然后使用它来声明您的变量:然后你就像这样使用它:当然,只要你重载函数,这一切都会失败.

  8. 在C中说“推动一切浮动”的确定性方式

    鉴于我更喜欢将程序中的数字保留为int或任何内容,那么使用这些数字的浮点数等效的任意算术最方便的方法是什么?说,我有我想写通过将转换放在解析的运算符树叶中,无需将表达式转化为混乱是否可以使用C风格的宏?应该用新的类和重载操作符完成吗?解决方法这是一个非常复杂的表达.更好地给它一个名字:现在当您使用整数参数调用它时,由于参数的类型为double,因此使用常规的算术转换将参数转换为double用C11lambda……

  9. objective-c – 如何获取未知大小的NSArray的第一个X元素?

    在objectiveC中,我有一个NSArray,我们称之为NSArray*largeArray,我想要获得一个新的NSArray*smallArray,只有第一个x对象…

  10. c – Setprecision是混乱

    我只是想问一下setprecision,因为我有点困惑.这里是代码:其中x=以下:方程的左边是x的值.1.105=1.10应为1.111.115=1.11应为1.121.125=1.12应为1.131.135=1.14是正确的1.145=1.15也正确但如果x是:2.115=2.12是正确的2.125=2.12应为2.13所以为什么在一定的价值是正确的,但有时是错误的?请启发我谢谢解决方法没有理由期望使用浮点系统可以正确地表示您的帖子中的任何常量.因此,一旦将它们存储在一个双变量中,那么你所拥有的确切的一

返回
顶部