最长公共子序列

前两天做了京东和网易的前端笔试题目,都是跟括号有关的....

京东的题目是:

最后求方案数,其实这道题本质上不难,但是需要挖掘题意,这道题需要我们逆向考虑,当碰到第一个右括号,其实它左侧的所有括号都可以与之匹配被删掉并且剩下的括号一定是有效的括号,但是每次过滤完一个右括号就要将左边现有剩下的左括号去掉一个

代码:

function getRes(str) {
    var res = 1,
        tmp = 0;
    for (var i = 0; i < str.length; i++) {
        if (str[i] == '(') {
            tmp++;
        } else {
            res *= tmp;
            tmp--;
        }
    }
    return res;
}

 

而网易的最后一道编程题是最长公共子括号序列

题解:因为要求的T需要和S不一样,所以T和S的最长公共子括号序列的长度最多为原字符串的长度N减1,而这个N-1可以通过只改变1个字符在S中的位置得到,方法是:遍历S,将每个位置上的字符尝试插入到剩余的字符串的任意位置上(两重循环),如果这个组合后的字符串是个合法的括号序列,那么它和原字符的公共子括号序列长度就是N-1,即最长,最后的结果是set集合大小减1的原因是里面还会包含原字符串

#include <iostream>
#include <set>
using namespace std;

bool isValid(string str) {
    int tmp = 0, len = str.size();
    for (int i = 0; i < len; i++) {
        tmp += (str[i] == '(') ? 1 : -1;
        if (tmp < 0) {
            return false;
        }
    }
    return true;
}

int main() {
    string str;
    cin >> str;
    set<string> S;
    int len = str.size();
    for (int i = 0; i < len; i++) {
        string w = str.substr(0, i) + str.substr(i+1);
        for (int j = 0; j < len - 1; j++) {
            string u = w.substr(0, j) + str[i] + w.substr(j);
            if (isValid(u)) {
                S.insert(u);
            }
        }
    }
    cout << (int)S.size() - 1 << endl;
}

 

今天就顺势学习了一下LSC算法:

主要思路:动态规划

设arr[i][j]表示第一个字符串s1的前i位与第二个字符串s2的前j位的最长公共子序列

如果i = 0 || j = 0,那么arr[i][j] = 0

如果 s1[i-1]=s2[j-1],那么arr[i][j] = arr[i-1][j-1] + 1(这里为什么是字符串之间i-1的比较但是却更新的是arr[i]呢?因为arr[][]是从1开始计算的,0的位置都是初始数据,但是字符串还是必须从0开始遍历的)

否则:arr[i][j] = Math.max(arr[i - 1][j], arr[i][j - 1]);

代码:

主要有两个功能,一个是求最长公共子串的长度,一个是打印出路径(采取标记法)

var record = [];

var str1 = "abcbdab",
    str2 = "bdcaba";

var len1 = str1.length,
    len2 = str2.length;

var lscString = "";

function getLSCLength() {
    var arr = [];
    for (var i = 0; i <= len1; i++) {
        arr[i] = new Array(len2 + 1);
        record[i] = new Array(len2 + 1);
        for (var j = 0; j <= len2; j++) {
            arr[i][j] = 0;
            record[i][j] = "";
        }
    }

    for (var i = 1; i <= len1; i++) {
        for (var j = 1; j <= len2; j++) {
            if (str1[i - 1] == str2[j - 1]) {
                arr[i][j] = arr[i - 1][j - 1] + 1;
                record[i][j] = 'left_up';
            } else {
                arr[i][j] = Math.max(arr[i - 1][j], arr[i][j - 1]);
                if (arr[i - 1][j] >= arr[i][j - 1]) {
                    record[i][j] = "up";
                } else {
                    record[i][j] = "left";
                }
            }
        }
    }
    return arr[len1][len2];
}

function LSC(i, j) {
    if (i == 0 && j == 0) return;
    if (record[i][j] == "left_up") {
        lscString += str1[i - 1];
        LSC(i - 1, j - 1);
    } else if (record[i][j] == "left") {
        LSC(i, j - 1);
    } else if (record[i][j] == "up") {
        LSC(i - 1, j);
    }
}

console.log("the longest subsequence length is " + getLSCLength());

LSC(len1, len2);

console.log("the longest subsequence is " + lscString);

 

转载于:https://www.cnblogs.com/chenyHAHA/p/7501512.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值