检查两个字符串是否按顺序具有相同的字符

时间:2011-12-01 16:54:46

标签: javascript regex

我如何在javascript中编写一个函数来返回两个字符串之间共享的字母数(按顺序)。

例如:如果两个字符串为readbread,则应返回4.

我正在考虑以某种方式使用循环,但似乎它会因很多迭代而变得非常复杂,而且我不知道从哪里开始。

有没有办法用正则表达式实现这一目标?可能,获取匹配的子字符串?然后可以从substring.length

导出长度

6 个答案:

答案 0 :(得分:2)

最长公共子串问题的algorithm有点棘手。我不认为有一种简单的方法可以与正则表达式相提并论。

答案 1 :(得分:1)

您应该使用其他算法答案之一。

话虽如此,这是一个正则表达式驱动的解决方案,只是为了好玩。为方便起见,在Perl中实现,相同的表达式将在JavaScript中起作用。

sub longest_common_substr_len{
    my $s = "$_[0]|$_[1]";
    my $l = 0;

    $l = length > $l? length: $l for $s =~ /(?=([^|]+)(?=[^|]*\|[^|]*\1))./g;

    return $l;
}

正则表达式找到所有*公共子串,循环得到最大长度。

它通过将两个字符串与一个特殊的分隔符连接起来(在这种情况下不能出现在字符串中,|),然后使用正则表达式查找(“本地最长”)子字符串(在每个字符处)这些都是分隔符之前和之后。

外部先行封装用于一次仅前进一个字符。没有它“zomg”和“zoomg”只会给2,因为“zomg”中的“zo”已被消耗而不允许“omg”匹配。

Example usage

say longest_common_substr_len "read", "bread";
say longest_common_substr_len "omgzomg", "omgomg";
say longest_common_substr_len "zomg", "zoomg";

输出:

4
3
3

答案 2 :(得分:0)

我想我会做的是:

  1. 查找两个字符串中的字符集
  2. 对于每一个,找到每个角色实例的最长匹配子字符串
  3. 查找共同的字符只是线性传递每个字符串,构建集合,然后交叉集合。它不仅可以跟踪字符,还可以跟踪索引(字符串中的位置)。这样,当你在做第二部分时,你不必搜索字符串来再次找到字符。

    不要为此投票;等到有人更聪明地尝试一下:-)(当然,你可以投票给我。)

    带有实现的

    Here is a jsfiddle。这是完成工作的JavaScript函数:

    function longestSharedSequence(str1, str2) {
        var seqs = {
            longest: null,
            all: []
        };
    
        function setOfChars(s) {
            var rv = {},
                c;
            for (var i = 0; i < s.length; ++i) {
                c = s[i];
                if (rv[c]) rv[c].push(i);
                else rv[c] = [i];
            }
            return rv;
        }
    
        function intersect(set1, set2) {
            var rv = {};
            for (var c in set1) {
                if (set1.hasOwnProperty(c) && set2.hasOwnProperty(c)) {
                    rv[c] = [set1[c], set2[c]];
                }
            }
            return rv;
        }
    
        function getSeq(pos1, pos2) {
            var seq = [str1[pos1]],
                i, j;
            for (i = pos1 + 1, j = pos2 + 1; i < str1.length && j < str2.length && str1[i] === str2[j]; ++i, ++j)
            seq.push(str1[i]);
            return seq.join('');
        }
    
        function getSeqs(positions) {
            var i, j, p1 = positions[0],
                p2 = positions[1],
                seq;
            for (i = 0; i < p1.length; ++i) {
                for (j = 0; j < p2.length; ++j) {
                    seq = getSeq(p1[i], p2[j]);
                    seqs.all.push(seq);
                    if (seqs.longest === null || seq.length > seqs.longest.length) {
                        seqs.longest = seq;
                    }
                }
            }
        }
    
        var set = intersect(setOfChars(str1), setOfChars(str2));
    
        for (var c in set) {
            if (set.hasOwnProperty(c)) {
                getSeqs(set[c]);
            }
        }
    
        return seqs.longest;
    }
    

答案 3 :(得分:0)

使用REGEX无法轻松完成。你应该使用嵌套循环。

<强> See this example

此示例中使用的代码:

function similarity(str1, str2) {
    count = 0;
    for (i = 0; i < str1.length; i++) {    //Loop through the letters of the first string
        for (j = i+1; j <= str1.length; j++) {   //Loop through the letters of the first string, starting from the letter in i.
            sub = str1.substring(i, j); //Slice the first string from i to j.
            //console.log(sub, count, str2.indexOf(sub), j, i);
            if (str2.indexOf(sub) != -1) {  //If the sliced string is found in the second string
                if (count < sub.length) { //If the count I currently have is lower then the current match I found
                    count = sub.length;
                }
            }
        }
    }
    return count;
}
alert(similarity('zzomg', 'omg'));

没有像我想象的那么多迭代。有n+(n-1)+n(n-2)+... = n^2-n没有歇斯底里的字符串(如50个字母)应该没问题。

答案 4 :(得分:0)

function longSubstrings(s1, s2, wbr, casesense){
    var temp= '', long= [], tem, tem2, str1, str2, len= 2, ax, L, i= 0;
    if(s1.length<s2.length){
        tem= s1;
        s1= s2;
        s2= tem;
    }
    // whole words match faster, if appropriate:
    wbr= wbr? ' ':'';
    // you can force a case sensitive match:
    str1= !casesense? s1.toLowerCase():s1;  
    str2= !casesense? s2.toLowerCase():s2;

    // normalize spaces:
    str1= str1.replace(/ {2,}/g, ' ');

    str2= str2.replace(/ {2,}/g, ' ');
    if(str1.indexOf(str2)!= -1) return s2;
    str1= str1.split(wbr);
    L= str1.length;
    while(i<L){
        tem= tem2= str1[i];
        ax= str2.indexOf(tem);
        while(ax!= -1){
            ++i;
            if(tem2.length>= len){
                len= tem2.length;
                long= long.filter(function(itm){
                    return itm.length>= len;
                });
                long.push(tem2);
            }
            tem2+= wbr+str1[i];
            ax= str2.indexOf(tem2);
        }
        ++i;
    }
    return long;
}
var s1= 'oie ja s a n y t nc eedjib n ife ks aio m io gna  red dogext x ia a dso zcq a a w eadz tie s matsa fw t seno e se pi iz t s j sv b n is t h toa p q osrf o tj e s ine to e io no xo sss jfytai oooic v puieo nnoveya ktnxk atl endtan uiu n s i enhro a a w k s s nlno iai ouex a t pals tnshp ia ais ga dnog rewen z ia bs t bbnn yeq sviiaio tto qe tnoimetn ntsoei i nsut oteh r iynnw ee gos moemtehlt k az q ri svft sc oot naagtc asste nl';
var s2= 'q meael a n o oia d fntqss ne assto nxs n y nx aoeog pho ev t n ao ste o it eoshi j aii x s infs g a il nho t alj ot isw ic ae si k oorateaw ts iug t b oi tn i m e vnos ss o jtn enoik kaon zseeaaitialsu ej a in ays t a nzyv m ibst sxuse t l eto od zs e y os zvinaieks w wq to ce ia ufs v k mrz e n taen d endtbatn tpteiu f gx hboati m o iieac op nef t atyno n p iatb cqaicsn d tt po r oae n n gsq nrne oe ij  red doga st eowsiie snhr';



    longSubstrings(s1, s2);
    //checks by character
    // returned value: (Array)
    red dog

    longSubstrings(s1, s2, 1);
    //checks whole words
    //returned value: (Array)
    red


// Older browsers need a shim for the filter method.
(or just write a loop for the filter)

if(![].filter){

        Array.prototype.filter= function(fun, scope){
            var T= this, A= [], i= 0, itm, L= T.length;
            if(typeof fun== 'function'){
                while(i< L){
                    if(i in T){
                        itm= T[i];
                        if(fun.call(scope, itm, i, T)) A[A.length]= itm;
                    }
                    ++i;
                }
            }
            return A;
        }
    }

答案 5 :(得分:-1)

正则表达式免费版

chaine1 = "bread";
chaine2 = "read";
if(chaine1.length <= chaine2.length){
    count = chaine1.length;
} 
else{
    count = chaine2.length;

}

var numberOfCharacterMatching = 0;

for (var i =0; i<count; i++){
if(chaine1.charAt(i) == chaine1.charAt(i)){
numberOfCharacterMatching++
}

}
alert(numberOfCharacterMatching++);