查找由其他字符串的字符组成的最长子字符串

时间:2013-12-03 07:22:47

标签: java string algorithm optimization complexity-theory

给出两个字符串:

str1 = "abcdefacbccbagfacbacer"
str2 = "abc"

我要找到str1中由str2字符子集组成的最长子字符串,在这种情况下它将是 - 7 (acbccba)。什么是解决这个问题的方法,至少复杂。首先我想到了DP。但是,我认为DP确实不是必需的,因为我们必须搜索子字符串,而不是子序列。然后我虽然后缀树。但这需要额外的预处理时间。

最好的方法是什么?实际上,这个问题是否适用于后缀树或DP?

4 个答案:

答案 0 :(得分:5)

迄今为止最简单的方法:

  1. 构建第二个字符串的哈希集。
  2. 循环遍历第一个字符串,并为每个字符检查它是否在哈希集中。跟踪最长的子串。
  3. 运行时间:O(n+m)其中nstr1的长度,mstr2的长度。


    (未经测试)代码:

    Set<Character> set = new HashSet<>();
    for (int i = 0; i < str2.length(); i++) {
        set.add(str2.charAt(i));
    }
    
    int longest = 0;
    int current = 0;
    int longestEnd = -1;
    for (int i = 0; i < str1.length(); i++) {
        if (set.contains(str1.charAt(i)) {
            current++;
            if (current > longest) {
                longest = current;
                longestEnd = i + 1;
            }
        } else {
            current = 0;
        }
    }
    
    String result = "";
    if (longest > 0) {
        result = str1.substr(longestEnd - longest, longestEnd);
    }
    

答案 1 :(得分:0)

实际上我只能想到一种方式:

  1. 继续字符串str1的字符。
  2. str1中的Foreach char检查它是否在str2中
  3. 每次在str2中找到str1中的当前char时增加一个计数器(i)
  4. 一旦str1中的char不是str2的一部分,则保存计数器(i)的值,如果它的数字是maxfound中的maxfound计数器,表示找到的最长序列并重置(i)计数器。

答案 2 :(得分:0)

只是一个想法:在[]中包装第二个字符串并使用Pattern的匹配方法:

Pattern p = Pattern.compile("(["+str2+"])");
Matcher m = p.matcher(str1);
m.find();

然后m.group(1)会找到它。

答案 3 :(得分:0)

Perl中经过测试的代码。

    use strict;
    use warnings;

    my $str1 = "abcdefacbccbagfacbacer";
    my $str2 = "abc";

    my @str1 = split ("", $str1);
    my @str2 = split ("", $str2);

    my @res = ();
    my $index = undef;
    my $max = 0;
    my @max_char = ();

    for(my $i = 0; $i < @str1; $i++){

        if ($str1[$i] =~ /[@str2]/){
            push (@res , $str1[$i]);
            next;
        }else{
            if(@res > $max){
                $max = @res;
                @max_char = @res;
                $index = $i;
            }
            @res = ();
        }
    }
    if(@res > $max){
        @max_char = @res;
        $index = $i;
    }

    $index = $index - $#max_char - 1;
    print "Longest substring = @max_char.  Starting from index $index";