0

对于本学期的最后一个项目,目标是在 Song 对象内的歌词字符串上运行特定短语的搜索,然后根据子字符串匹配的长度对结果进行排名。歌词是从文件中读取的,并与该文件中的换行符匹配。

例如,搜索“她爱你”将在示例匹配中返回这些:

披头士乐队:“......她爱你,是的,是的,是的......” Rank= 13 个字符
Bonnie Raitt:“......只是爱你......” Rank= 18 个字符
Elvis Presley:“......你在问她是否爱我\r\n嗯,不知道……” Rank= 23 characters

从上一个示例中可以看出,匹配项可以跨越多行。

我有 a 中的所有歌曲TreeMap<String, TreeSet<Song>>,所以我得到了与查询中的第一个单词匹配的所有歌曲。我遇到的困难是在字符串中搜索匹配项,因为正则表达式在这种情况下不起作用。

构造 Song 对象时,我将歌词转储到 Set 中以运行单个单词的搜索,为此我曾经String.split("[^a-zA-Z}")分离出单个单词并清除标点符号。所以我想在那个数组上运行我的搜索。我正在使用的过程如下:

break up the query into a String array
  for each Song in the set
    if (song.lyrics.contains(query)
      great, break loop to next song

    otherwise
      int queryCounter=0;
      find first index point in String array that matches query[queryCounter]
        using that as the start point, iterate through the String array for matches

迭代完成后,会创建一个 Rank 对象来保存匹配的数组部分的歌曲、搜索短语、起点和终点。在 Rank 对象中是一种计算字符数并补偿空格来计算排名的方法。然后将其插入到 PriorityQueue 中,将从原始 matchSet 中提取前十个匹配项。

问题是这并不能防止误报,并且匹配排名可能会出现偏差。例如,Aerosmith 的 Beyond Beautiful 包含“……她爱我,她不爱你……”在我的过程中,我将匹配“……她爱我,她不爱……”,所以不是排名13,我将获得27的排名。

我需要进行哪些更改才能清除误报和不正确的排名?

4

1 回答 1

1

我想补充一下 jjinguy 所说的:

基本上,在“否则”块中,在找到第一个与起点匹配的索引后,您还必须寻找可能的其他起点,如果找到另一个起点,则重置起点

我会保留一首歌中所有可能匹配的列表,最后使用排名最高的匹配。简单地重新设置起点可能无法赶上排名最高的比赛。

也许这不是最好的方法,但担忧仍然存在。

于 2010-11-11T15:17:48.487 回答