两个字符串之间的子串差异

时间:2012-02-20 04:52:56

标签: java string algorithm

给定两个长度为n的字符串,P = p1 ... pn和Q = q1 ... qn,我们将M(i,j,k)定义为pi ... pi + k-之间的不匹配数1和qj..qj + k-1。这是设定符号,M(i,j,k)是指集合{ 0<=x<k | pi+x not equal to qj+x| }的大小。

给定一个整数K,你的任务是找到最大长度L,使得存在一对索引(i,j),我们有M(i, j, L) <= K。当然,我们也应该有i+L-1 <=nj+L-1 <=n。 输入

第一行输入包含单个整数T(1 <= T <= 10)。 T测试案例如下。 每个测试用例由一个整数K和两个由单个空格分隔的字符串P和Q组成。 输出

对于每个测试用例输出一个整数L,它是存在一对索引(i,j)的最大值,使得M(i,j,L)<= K。

约束

0 <= K <=字符串P的长度 P&amp; P&amp; Q的长度相同 每个字符串的大小最大为1500 P&amp;中的所有角色Q是小写英文字母。

示例输入

3
2 tabriz torino
0 abacba abcaba
3 helloworld yellomarin

示例输出

4
3
8 

说明:   第一个测试用例:如果我们从第一个字符串中取“briz”,从第二个字符串中取出“orin”,那么这两个子串之间的不匹配数等于2,这些子串的长度为4.那就是我们选择i = 3,j = 2,L = 4,我们得到M(3,2,4)= 2.

第二个测试用例:由于K = 0,我们应该找到给定输入字符串的最长公共子字符串。我们可以选择“aba”作为结果,并且我们在两个字符串之间没有更长的公共子串。所以,这个测试用例的答案是3。我们选择i = 1,j = 4,L = 3,我们得到M(1,4,3)= 0.

第三个测试用例:我们可以从第一个字符串中选择“hellowor”,从第二个字符串中选择“yellomar”。所以,我们选择i = 1,j = 1,L = 8,我们得到M(1,1,8)= 3。当然我们也可以选择i = 2,j = 2,L = 8,我们仍然有M(2,2,8)= 3.

这是我的实现

import java.io.*;
import java.util.*;

class Solution {

    public static int mismatch(String a, String b, int ii, int jj, int xx) {
        int i, j = 0;
        for (i = 0; i < xx; i++) {
            if (a.charAt(ii) != b.charAt(jj)) {
                j++;
            }
            ii++;
            jj++;
        }
        return j;
    }

    public static boolean find(int x, String a, String b, int kx) {
        int nn = a.length();
        for (int i = 0; i <= (nn - x); i++) {
            for (int j = 0; j <= (nn - x); j++) {
                int k;
                k = mismatch(a, b, i, j, x);
                if (k == kx) {
                    return true;
                }
            }
        }
        return false;
    }

    public static void main(String args[]) throws IOException {
        Scanner scanner = new Scanner(System.in);
        int t = scanner.nextInt();
        while (t > 0) {
            int k, n;
            String a, b;
            k = scanner.nextInt();
            a = scanner.next();
            b = scanner.next();
            n = a.length();
            int i = (n + k) / 2;
            int st = k, en = n
                while (i != k || i != n) {
                boolean ch = false, chh = false;
                ch = find(i, a, b, k);
                if (i != n) {
                    chh = find(i + 1, a, b, k);
                }
                if (i == n && ch == true) {
                    System.out.println(i);
                    break;
                }
                if (ch == true && chh == false) {
                    System.out.println(i);
                    break;
                }
                if (ch) {
                    st = i;
                    i = (i + en + 1) / 2;
                } else {
                    en = i;
                    i = (st + i) / 2;
                }
            }
            t--;
        }
    }
}

上述实现输入为1500字符串长度需要5.1秒。但java中的最大时间限制为5秒。如果任何人都可以改进此代码,请分享你的想法

2 个答案:

答案 0 :(得分:1)

您的代码在网站上不占用5.1。一旦超过时间限制,它们就会停止运行您的代码。您的代码可能需要几分钟。因此,即使您使用此算法对其进行优化,您也会在详细信息部分再次获得5.1s。所以你的算法就算了,而不是优化!

答案 1 :(得分:0)

您可以创建一个布尔数组compare[n,n]compare[i,j]=(a[i]==b[j]).稍后使用它而不是重复比较。你将无比无比的比较和解决。

public static int mismatch(String a, String b, int ii, int jj, int xx) {
    int i, j = 0;
    for (i = 0; i < xx; i++) {
        if (! compare[ii,jj]) {
            j++;
        }
        ii++;
        jj++;
    }
    return j;
}