Steve Hanov

stevehanov.ca · Personal blog · on HN since 2009

Steve Hanov, a programmer and founder, writes about algorithms, data structures, A/B testing, and running small software businesses.

What HN saysCommenters call his articles classics, especially on bandit algorithms and tries, and say they have followed his C++-heavy blog for years.
106HN people shared it
54linked it in comments
72stories submitted
3.8Kstory points
7 months agolast shared
2009people per year2026

Most-shared posts

  1. 1
    20 lines of code that beat A/B testing every time
    11 people · 1.9K points · first shared 2012 · 176 comments on HN
  2. 2
  3. 3
  4. 4
    How a programmer reads a resume
    6 people · 56 points · first shared 2010 · 53 comments on HN
  5. 5
    Game Theory, Salary Negotiation, and Programmers
    6 people · 11 points · first shared 2010 · 1 comments on HN
  6. 6
    Minimal Perfect Hashing
    5 people · 86 points · first shared 2011 · 10 comments on HN
  7. 7
    Fast and easy Levenshtein distance using a trie (2011)
    4 people · 168 points · first shared 2011 · 38 comments on HN
  8. 8
    Fast Levenshtein distance using a Trie
    4 people · 107 points · first shared 2011 · 16 comments on HN
  9. 9
    C++: A language for next generation web apps
    4 people · 104 points · first shared 2010 · 95 comments on HN
  10. 10
  11. 11
    HR vs. programmers – how they reads your resume
    4 people · 1 points · first shared 2010 · discussion on HN
  12. 12
  13. 13
    VP trees: A data structure for finding stuff fast
    3 people · 113 points · first shared 2011 · 9 comments on HN
  14. 14
    Qb.js: An Implementation of Qbasic in JavaScript
    3 people · 6 points · first shared 2021 · discussion on HN
  15. 15
    Compressing dictionaries with a DAWG
    3 people · 6 points · first shared 2011 · discussion on HN

What HN people wrote when they linked it

ignoramous · 2022-07-22
See Steve Hanov's classic article on the topic: http://stevehanov.ca/blog/index.php?id=120
karterk · 2019-07-14
The trie is my favorite data structure. It allows you to build inverted indices (i.e. hashmaps) that can also be used for prefix lookups of tokens and for spelling/typo correction. With a trie, it's very efficient to calculate Levenshtein distances. Here's a post (http://stevehanov.ca/blog/?id=114) that has a good primer on that. If you love this sort of thing, here's a fast and neat memory efficient Trie variant: https://db.in.tum.de/~leis/papers/ART.pdf (Adaptive Radix Tree). I've used ART as a building block to create an open source typo tolerant search engine called Typesense (https://github.com/typesense/typesense).
rurban · 2018-05-14
True. A gperf alike hash table (with special key indices) works only ok with compile-time known strings. But a simple CMP-alike perfect hash table with double indirection would be worthwhile to test against. I called it Hanov after http://stevehanov.ca/blog/index.php?id=119 Problem is there that you have to calc a hash for each string, which is only fast with __builtin_crc/_mm_crc32_u64
emcrazyone · 2015-12-04
It is relatively easy. I've done it myself many moons ago. I've followed Steve off and on over the years. He seems to prefer C++ as a web-app language so much so that he blogs about it and other things. I like his stuff. I discovered Steve through Joel On Software some years ago. If memory serves me, I think at one time he was publishing a Web CMS type engine written in C++ but I could have him confused with someone else (been awhile) Here is his site: http://stevehanov.ca/blog/index.php?id=95
splitforce · 2014-05-27
Thanks, we think it's pretty cool too! And you've totally hit on why this is awesome - by automatically funneling users towards better-performing variations you can focus your resources on validating what matters and cut down on the deadweight loss associated with a traditional A/B. For more on this here's a recommended read: http://stevehanov.ca/blog/index.php?id=132?utm_medium=referral
jones1618 · 2012-10-11
Just because a problem has been "solved" for one platform (Fast PC's w/ Gigabytes of ram/disk) doesn't mean it is solved for all platforms (Web apps for phones/tablets, etc). John Resig (of jQuery and Khan Academy fame) had a really interesting thread on creating a fast-loading (i.e. small, efficient) dictionary for a JavaScript app. http://ejohn.org/blog/revised-javascript-dictionary-search/ The comments have some really clever ideas for encoding the dictionary and Resig weighs in on his favorite solution with informative data. There's an interesting "Succinct Trie" data structure that turns a 620K dictionary into a 220K string that doesn't need to be decoded to be searched. http://stevehanov.ca/blog/index.php?id=120
lchengify · 2010-08-25
Make sure your resume follows this (not joking): http://stevehanov.ca/blog/index.php?id=56 Also practice coding on a whiteboard. Some problems, like running out of vertical space, are things you don't run into on a computer.
geirk · 2010-01-27
If this guy is really running his web server on an Acer Aspire One 512, as he says at http://stevehanov.ca/blog/index.php?id=71 C++ sounds like an excellent choice.
RiderOfGiraffes · 2009-08-29
http://stevehanov.ca is a respected site with some really cool stuff. The fact that the telephone number bit doesn't work is surprising and unusual for the site, and I'm interested in why it's not working. The question was intended to try to pin down why it didn't work. I'm confused as to why I got downvoted. It's not a complaint, I accept that perhaps someone feels the question is of negative value to this site. Fine. But an explanation as to why would be appreciated. Help me to understand.
karanbhangui · 2009-08-27
http://stevehanov.ca/blog/index.php?id=81 Excellent post on a more advanced implementation.
Loic · 2015-03-07
Effectively, you need to keep a small heap and if possible have "simple" data structure. In my case, I implemented the Python code of a trie based levenshtein distance algorithm[0]. I used maps because it was basically a direct translation of the Python code. This resulted in millions of maps and oft the index would just stop in the garbage collector for a couple of seconds. I solved it using my own map which is travelled linearly. type SpellCheckerMap struct { Runes []rune Nodes []*SpellCheckerNode } with only few runes, I can just go through the list to find the index of the following node. You save the computation of the map hash key. It is pretty fast, here is an example of a spelling suggestion over a 500,000 words corpus[1]. Basically, the garbage collection cost forced me to think about a better data structure for my case. Maybe not that bad all in all. [0]: http://stevehanov.ca/blog/index.php?id=114 [1]: https://www.chemeo.com/search?q=asparine
btilly · 2012-05-30
Most or all of the points suffer from: Let's address them one by one. is that actually true? In every case, yes. does regular a/b testing not also face that issue? For the big ones, regular A/B testing does not face that issue. For the more complicated ones, A/B testing does face that issue and I know how to work around it. With a bandit approach I'm not sure I'd have noticed the issue. was it suggested that you must "set it and forget it"? Not "must", but it was highly recommended. See paragraph 4 of http://stevehanov.ca/blog/index.php?id=132 - look for the words in bold. are there no mechanisms for mitigating these issues? There are mechanisms for mitigating some of these issues. The blog does not address those. As soon as you go into them, you get more complicated. It stops being the "20 lines that always beats A/B testing" that the blog promised. I was doing some back of the envelopes on different methods of mitigating these problems. What I found was that in the best case you turn into would using 20% or 30% mitigate the issues? That would lessen the issue that I gave, at the cost of permanently worse performance. The permanent performance bit can benefit from an example. Suppose that there is a real 5% improvement. The blog's suggested approach would permanently assign 5% of traffic to the worse version, for 0.25% less improvement than you found. Now suppose you tried a dozen things. 1/3 of them were 5% better, 1/3 were 5% worse, and 1/3 did not…
kristianp · 2026-04-16
The author also has an interesting discussion of Succinct Data Structures at https://stevehanov.ca/blog/succinct-data-structures-cramming-80000-wor…
leafmeal · 2025-03-07
There's a create blog from the creator of RhymeBrain that talks about Succinct Tries: https://stevehanov.ca/blog/index.php?id=120 I'm pretty sure these were used to store the built in dictionaries on early mobile phones, especially for the implementation of T9 word and similar programs.
nayuki · 2025-01-13
Funny you say that because multi-armed bandits is one of the articles on the front page right now. https://stevehanov.ca/blog/index.php?id=132 , https://news.ycombinator.com/item?id=42650954
adontz · 2022-07-22
Succinct Trie http://stevehanov.ca/blog/?id=120 Super effective way to store a searchable list of items, like a dictionary of words.
Rendello · 2021-11-17
OP here. As an aside, I feel like I tick a lot of boxes in the bottom section of this comic (I know it's a meme, but perhaps still relevant somehow), but perhaps I do worst when HR is looking for schooling, etc. http://stevehanov.ca/blog/resume_comic.png
Cybiote · 2021-11-04
An in-between option that is relatively simple and a rather fast (though not as fast as the automata) optimization to levenstein distance and based on Tries is: http://stevehanov.ca/blog/?id=114.
Cthulhu_ · 2021-05-31
There's this one for qbasic: http://stevehanov.ca/blog/?id=92
dr_dshiv · 2020-04-18
I'm interested in scalograms and continuous wavelet transforms. Here's something from a few years back http://stevehanov.ca/blog/?id=22
I think practical solution to this is to return all words that are within a Levenshtein distance[1] of 2*number_accented_characters of the original word, ranked by the distance. Levenshtein distance can be calculated using a trie[2] so it's fast enough for most purposes. If you wanted to get fancy you could modify the Levenshtein to reduce the distance penalty on accented characters, and/or only apply the Levenshtein calculation within 1 character of an accented character or the equivalent ASCII substitution sequence. [1] https://en.wikipedia.org/wiki/Levenshtein_distance [2] http://stevehanov.ca/blog/?id=114
LVB · 2017-11-06
I must say, I was happy to come across this after putting in the not insignificant effort of converting my resume into a nice looking LaTeX document: http://stevehanov.ca/blog/resume_comic.png
socmag · 2017-04-03
Yes interesting stuff. Seems similar in nature to "Vantage Point" trees. http://stevehanov.ca/blog/index.php?id=130
mysterydip · 2017-03-06
Could you apply what you learned to improve this qb js interpreter? http://stevehanov.ca/blog/index.php?id=92 Fairly useless but would be a nice nostalgia trip to be able to run some of the 90s qbasic code that's still lying around in unswept corners of the internet :)
dikaiosune · 2016-01-21
I've always liked the idea of using "systems" languages for data shuffling, because of the ability in some cases to stretch hardware several orders of magnitude further. I read this a while ago and just dug it up: http://stevehanov.ca/blog/index.php?id=95 It's a bit silly, but I do think that Rust could be a very good solution here. For one thing, in my experience it is much easier to write than C++, especially for something you'd feel comfortable pointing at users. It would be cool to see some articles that are the reverse of "scale all the things," something like "sympathize with all the caches."
duhruh · 2015-12-04
A better alternative to your simple a/b test would be the multi-armed bandit algorithm. This will give you your answer the fastest, though it's slightly harder to wrap your head around check it out here: http://stevehanov.ca/blog/index.php?id=132
sixtypoundhound · 2013-12-18
These are not the data structures you are looking for, move along... A good source on this subject, with applications, is Steve Hanov's blog (read a year or so back - he started an ISV and his recent scope expanded to include business issues...): http://stevehanov.ca/blog/index.php
relaunched · 2013-05-06
A/B Testing Rigorously Without Losing Your Job - B. Tilly - http://elem.com/~btilly/ab-testing-multiple-looks/part1-rigorous.html 20 Lines of Code that Will Beat A/B Testing Every Time - S. Hanov - http://stevehanov.ca/blog/index.php?id=132 These are the ones I've read recently. If I remember any others, I'll update.
stonemetal · 2012-08-14
One of the draw backs that typically gets mentioned about current distributed systems is the lack of locking which makes managing un-merge-able (binary) files impossible to manage correctly. This is why you will not hear of many game dev studios using git, version controlling art assets is fairly common in such situations and perforce handles it like a champ. DVCSs in general tend to have performance issues with large files, I know mercurial warns you about the performance implications of storing anything over 10MB. A bit old(2009) so it may have changed, but here is a rant about the scalability of git vs perforce. http://stevehanov.ca/blog/index.php?id=50 and a little newer post on git scalability issues: http://news.ycombinator.com/item?id=3548824

Keyboard shortcuts

/Search
j kNext / previous blog
EnterOpen selected blog
vVisit the blog site
fFollow / unfollow
lSwitch grid / list view
dSwitch dark mode
g hHome
g pTop posts
g tTopics
g fFollowing
g lLiked
g yHistory
g qFAQ
EscBack / close