Skip to content

HJ75 公共子串计算

题目描述

image-20220214101815644

示例

image-20220214101825303

代码

动态规划,使用一个二维数组记录状态转移

js
/*
计算两个字符串的最长公共子串

asdfas
werasdfaswer

输出:6
最长的子串为 asdfas 

使用动态规划,思路参考 
https://www.bilibili.com/video/BV1aK411J7b8?from=search&seid=16339578023628360686&spm_id_from=333.337.0.0

构建一个状态转移的二维数组,用来存状态
比如 str1= acgta    str2 = aacgttag
我们肉眼可见 最长的公共子串是 acgt,所以最终输出的结果是 长度 4

动态规划构建的状态转移数组如下
      a  a  c  g  t  t  a  g
   0  0  0  0  0  0  0  0  0
a  0  1  1  0  0  0  0  1  0
c  0  0  0  2  0  0  0  0  0
g  0  0  0  0  3  0  0  0  1
t  0  0  0  0  0  4  1  0  0
a  0  1  1  0  0  0  0  1  0

所以输出的就是 4 

状态转移的方程为
if(a === b){
    table[row][col] = table[row-1][col-1] + 1
} else {
    table[row][col] = 0
}

*/

let readline  = require('readline')
let rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
})

let inputArr = [] // 记录输入的值

rl.on('line', line=>{
    
    // 记录输入的值
    inputArr.push(line)
    
    if(inputArr.length === 2){ // 输入两个字符串的时候,计算结果
        let [ str1, str2 ] = inputArr
        let len1 = str1.length
        let len2 = str2.length
        
        // 初始化一个dp二维数组,全部填充0
        let dp = new Array(len1+1).fill([]).map(()=>{
            return new Array(len2+1).fill(0)
        })
        
        let max = 0 // 默认最大子串长度为0
        
        // 两层循环 开始遍历(从索引1开始遍历,因为要从二维数组的第二行第一列的第一位开始计算)
        //(二维数组的第一行第一列是预留的0,为了计算状态)
        for(let i = 1; i < len1+1; i++){
            for( let j = 1; j < len2+1; j++ ){
                let a = str1[i-1]
                let b =  str2[j-1]
                if(a === b){
                    dp[i][j] = dp[i-1][j-1] + 1
                }
                // 记录当前最大长度
                if(dp[i][j] > max){
                    max = dp[i][j]
                }
            }
        }
        console.log(max) 
        
        // 每次计算一次结果后 清空输入输入,便于接下来的计算
        inputArr.length = 0
        
    }
})

题目来源

HJ75 公共子串计算

题解参考

https://www.bilibili.com/video/BV1aK411J7b8?from=search&seid=16339578023628360686&spm_id_from=333.337.0.0