很多首詩,每首詩中包含很多字。我當然要用倒排索引了,對每個字建立索引,形式如下:
字1 詩11 詩12 詩13
字2 詩21 詩22
......
用戶查詢的是一個詩句,我把這個詩句中的每個字都摘出來去倒排索引里找,把每個字對應的集合做AND操作,得到一個詩的集合。
現在問題來了,如何對這個詩的集合排序?
這個問題其實就是相關度排序。最小編輯次數、最長公共子序列雖然也是一種排名方法,但容錯性較低。比如我把“床前明月光”寫成了“明月床前光”,最好也能夠容忍我這種錯誤。
這肯定跟字在詩中的位置有關系,這些字離得越近越好。於是想到了使用方差。
在倒排索引中,加入“字位”信息。對於一首詩,字位信息如下:
字1 位置11 位置12 位置13
字2 位置21 位置22 位置23
字3 位置31 位置32 位置33
......
形式化一下這個問題:
給定N個集合,從每個中選取1個元素組成新的集合,使得新集合中元素方差最小,這個最小方差即為這N個集合的“得分”。
這個問題應該怎么做呢?
根據學過的算法可以很容易地構造出幾個不一定正確的算法:
-
動態規划,定義二維數組f,f[i][j]表示前i個集合的最小方差並且最后一個數字是第i個集合中的第j個元素。當走出一條路徑之后,對這條路徑求均值,最佳路徑必然是路徑上的每一個結點都盡量靠近平均值,反復迭代更新,直到無法更新為止。
上面這種動態規划思想有點馬爾科夫過程維特比算法的意思。 -
貪心,一開始把全部點放進一個盒子,求平均值,把離平均值最遠的那個點刪掉,如果某集合中只剩下一個點則這個點不可刪。如此貪心,每次刪除離均值最遠的點,知道無法刪除,即為所求。
-
如果集合個數小於16,並且集合中每個數字都比較小(比如小於1000),那么可以用動態規划,f[i][j]中的i表示二進制的集合狀態(也就是有沒有訪問過),j表示當前的平均數,f[i][j]表示當前的方差。
上面這種想法對不對呢?