JavaScript实现歌曲和弦重复模式自动识别的技术方案求助
问题:识别歌曲和弦重复模式的JavaScript实现方法
我用JavaScript开发,想找识别歌曲和弦重复模式的实现方法。以下是输入示例(《加州旅馆》和弦):
Am E7 G D F C Dm E7 F C E7 Am F C Dm E7 Am E7 G D F C Dm E7 Am E7 G D F C Dm E7 F C E7 Am F C Dm E7 Am E7 G D F C Dm E7 Am E7 G D F C Dm E7 F C Dm E7 Am E7 G D F C Dm E7 Am E7 G D F C Dm E7 Am E7 G D F C Dm E7 Am E7
期望输出结果:
Am E7 G D F C Dm E7 F C E7 Am F C Dm E7 Am E7 G D F C Dm E7 Am E7 G D F C Dm E7 F C E7 Am F C Dm E7 Am E7 G D F C Dm E7 Am E7 G D F C Dm E7 F C Dm E7 Am E7 G D F C Dm E7 Am E7 G D F C Dm E7 Am E7 G D F C Dm E7 Am E7 G D F C Dm E7
需求说明:自动识别重复模式,要求最小模式长度为3(避免过短匹配);识别出的模式如示例中的Am E7 G D F C Dm E7和F C E7 Am F C Dm E7,用这些模式分割原和弦序列,非模式部分原样保留。
可行实现思路
简易方案:滑动窗口统计+贪心匹配
- 预处理和弦序列:把输入字符串按空格分割成和弦数组,示例代码:
const chords = input.split(/\s+/).filter(Boolean); - 统计高频子序列:
- 遍历所有可能的子序列长度,从数组长度的1/2开始往下到3(优先找长模式)
- 对每个长度
len,用滑动窗口遍历数组,将每个窗口内的和弦用特殊字符(如逗号)连接成字符串作为键,统计每个键的出现次数 - 筛选出现次数≥2的子序列,按长度从长到短排序
- 贪心分割原序列:
- 从数组起始位置开始,依次尝试匹配最长的候选模式
- 匹配成功则输出该模式,跳过对应长度的和弦;匹配失败则逐个取和弦,直到找到可匹配的模式,或直接输出无法匹配的零散部分
- 匹配完成后从下一个位置继续,不回头处理重叠情况
复杂方案:基于后缀数组的模式识别
- 构建后缀数组:提取和弦数组的所有后缀(从第i个元素到末尾的子数组),生成后缀数组
- 寻找最长重复子串:计算后缀数组中相邻元素的最长公共前缀(LCP),筛选出长度≥3的最长重复子序列,这些就是核心重复模式
- 模式去重与排序:对找到的重复模式去重,优先保留长度长、出现次数多的模式
- 序列分割优化:用动态规划计算最优分割方式,尽量用最少的模式覆盖原序列,同时保留无法匹配的零散部分
关键细节处理
- 最小长度限制:所有候选模式的长度必须≥3,过滤更短的子序列
- 避免误匹配:统计模式时,确保子序列在原数组中是连续出现的,而非零散分布
- 输出格式:分割后的每个模式或零散部分单独占一行,保持和弦间的空格
内容的提问来源于stack exchange,提问作者Yohan Attal
相关产品推荐
相关产品推荐

