Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 替换字符及其所有匹配项后,计算匹配字符串的数目_Java_String_Algorithm - Fatal编程技术网

Java 替换字符及其所有匹配项后,计算匹配字符串的数目

Java 替换字符及其所有匹配项后,计算匹配字符串的数目,java,string,algorithm,Java,String,Algorithm,我有一个字符串数组arr和另一个输入字符串s 现在我的任务是从s中选择一个字符,并用另一个字符替换s中出现的所有字母。然后根据需要重新排列字符,但这是可选的。现在计算其中有多少与数组元素匹配 我已经用Java编写了这方面的代码,但是我所采用的方法是不正确的 示例: s=aabbcdbb arr = {"aabbcdbbb", "aabbcdb", "aabbxdbb", "aabbbdbb", "aaccc

我有一个字符串数组
arr
和另一个输入字符串
s

现在我的任务是从
s
中选择一个字符,并用另一个字符替换
s
中出现的所有字母。然后根据需要重新排列字符,但这是可选的。现在计算其中有多少与数组元素匹配

我已经用Java编写了这方面的代码,但是我所采用的方法是不正确的

示例: s=aabbcdbb

arr = {"aabbcdbbb", "aabbcdb", "aabbxdbb", "aabbbdbb", "aacccdcc", "ddbbcdbb", "eebbcdbb"}
输出

5
说明:

length of s = 8
sorting s = aabbbbcd

arr[0] = has 9 characters i.e more than s length so ignored
arr[1] = has 7 characters i.e less than s length so ignored
arr[2] = sorting : aabbbbdx. replace x with c and rearranging it makes this as aabbbbcd
arr[3] = sorting : aabbbbbd. replace 1 occurrence of b with c and rearranging it makes this as aabbbbcd
arr[4] = sorting : aacccccd. replace 4 occurrences of c with b and rearranging it makes this as aabbbbcd
arr[5] = sorting : bbbbcddd. replace 2 occurrences of d with a and rearranging it makes this as aabbbbcd
arr[6] = sorting : bbbbcdee. replace e with a and rearranging it makes this as aabbbbcd

so arr[2], arr[3], arr[4], arr[5], arr[6] matches the given requirement so output is 5.
我尝试了此程序,但某些输入失败:

static int process(String s, String[] arr) {
    int matches = 0;
    Map<Character, Integer> m = new HashMap<>();
    
    // sort s
    char[] c = s.toCharArray();
    Arrays.sort(c);
    s = new String(c);
    c = s.toCharArray();
    
    // get each char of s and count its occurrences
    for(char k : c) {
        m.put(k, m.getOrDefault(k, 0)+1);
    }
    
    for(String s1 : arr) {
        // get array element
        char[] c1 = s1.toCharArray();
        // check if array element length matches with input string length
        if(c1.length == c.length) {
            // count each occurrence of char into array of alphabets
            int[] chars = new int[26];
            for(char k1: c1) {
                chars[k1-'a']++;
            }
            
            // decrement count by checking with map
            for(char k : m.keySet()) {
                chars[k-'a'] -= m.get(k);
            }
            
            boolean f1 = false;
            boolean valid = true;
            int mismatch = 0;
            int notzeros = 0;
            // get each element from array of chars
            for(int i=0; i<26; i++) {
                int ch = chars[i];
                // value not zero
                if(ch != 0) {
                    // count number of non zeros
                    notzeros++;
                    // f1 is true, means its second occurrence of non zero element
                    if(f1) {
                        if(ch > 0) {
                            // check if values do not match
                            if(mismatch*-1 != ch) {
                                valid = false;
                                break;
                            }
                        } else {
                            // check if values do not match
                            if(mismatch != ch*-1) {
                                valid = false;
                                break;
                            }
                        }
                    }
                    // get the mismatch count and set the value of flag to true
                    f1 = true;
                    mismatch = ch;
                }
                // if non zero elements more than 2 then we can ignore this array element
                if(notzeros > 2) {
                    valid = false;
                    break;
                }
            }
            //  check for possible solution.
            if(valid && f1) {
                matches++;
            }
        }
    }
    return matches;
}

我解决这项任务的方法不正确,正确的方法是什么?

首先,您提供的解释似乎是基于对问题的一个稍微误解的表述。问题在于检查是否可以用字符串s中的不同字符而不是数组中的字符串替换出现的所有字符。

因此,例如,使用
s=“aabbcdbb”
和数组字符串
“aabbbdbb”
,您可以将
s
中的
c
字符替换为
b
,以获得数组字符串。不是相反的。这解释了两个输入样本的预期输出的不一致性(如注释中所述)

您的实现通常是正确的,但在特殊情况下失败。解决这个问题的方法基本上是生成一个“diff”数组,其中包含每个字符出现的差异。然后,您希望在diff中,只有两个不同的事件相互抵消。要使用上一个示例进行说明,请映射
s
的字符:

a -> 2
b -> 4
c -> 1
d -> 1
与当前数组元素类似:

a -> 2
b -> 5
d -> 1
区别在于:

b -> 1
c -> -1
如果您有
s=“aabb”
和字符串
“abbb”
,则此操作失败,其中差异为:

a -> -1
b -> 1
这里的问题是,字符
a
b
都出现在字符串
“abbb”
中。这将使匹配检查失败。原因是:如果我们想从
“abbb”
转到
“aabb”
,我们需要用
a
替换
b
。但是
“abbb”
已经有一个
a
字符,如果对方用
b
替换
a
,该字符就不存在了

可以修改代码以处理这种情况(使用
diffInS1
的部件):

for(字符串s1:arr){
//获取数组元素
char[]c1=s1.toCharArray();
//检查数组元素长度是否与输入字符串长度匹配
如果(c1.length==c.length){
//将每次出现的字符计数到字母表数组中
int[]字符=新int[26];
int[]diff=新的int[26];
用于(字符k1:c1){
字符[k1-'a']++;
差异[k1-'a']++;
}
//通过使用map进行检查来减少计数
for(字符k:m.keySet()){
diff[k-'a']=chars[k-'a']-m.get(k);
}
布尔有效=真;
int不匹配=0;
int notzeros=0;
int-diffInS1=0;
//从字符数组中获取每个元素
对于(int i=0;i 1){
//检查值是否不匹配
如果(不匹配*-1!=ch){
有效=错误;
打破
}
}
如果(字符[i]>0){
diffInS1++;
}
//获取不匹配计数
失配=ch;
}
//如果非零元素大于2,则可以忽略此数组元素
如果(非零>2 | | diffInS1==2){
有效=错误;
打破
}
}
//检查可能的解决方案。
if(有效的&¬zeros>0){
匹配++;
}
}
}

我将提供类似的方法。让我们分析两个字符串何时“替换一个字符及其所有匹配项后匹配字符串”。假设我们有两个
char
count的映射。现在我们需要计算它们的差异。当两个左映射有一个条目且计数器相等时,两个字符串匹配

让我们做一个例子<代码>aabbcd将创建地图:

a -> 2
b -> 4
c -> 1
d -> 1
aabbxdbb
将创建:

a -> 2
b -> 4
x -> 1
d -> 1
区别在于:

b -> 1
c -> -1
第一张地图将保留:

c -> 1
第二张地图:

x -> 1
因此,这两个人是匹配的。让我们看看如何写这个

首先,这是获取此地图的方法:

private static Map<Character, Integer> getMap(String s) {
    Map<Character, Integer> result = new HashMap<>();
    for (char c : s.toCharArray()) {
        if (result.containsKey(c)) {
            result.put(c, result.get(c) + 1);
        } else {
            result.put(c, 1);
        }
    }
    return result;
}
我们得到了输出:

aabbcdbb and aabbcdbbb cannot be replaced.
aabbcdbb and aabbcdb cannot be replaced.
aabbcdbb and aabbxdbb can be replaced. Replace 1 instances of c with 1 instances of x
aabbcdbb and aabbbdbb can be replaced. Replace 1 instances of c with 1 instances of b
aabbcdbb and aacccdcc can be replaced. Replace 4 instances of b with 4 instances of c
aabbcdbb and ddbbcdbb can be replaced. Replace 2 instances of a with 2 instances of d
aabbcdbb and eebbcdbb can be replaced. Replace 2 instances of a with 2 instances of e
Replacables count: 5

调试。所以,在你的测试中,你期望结果是1,但你得到了2。当您调试导致结果计数的两种情况时,一种是100%正确,另一种是错误的吗?为什么会出现不正确的匹配?@jarmod,我发现我采用的方法本身是错误的,我已经调试了代码。这两种解释相互矛盾。在第一种情况下,您只替换出现的一些字符,这是正常的,但在第二种情况下,这是不正常的。如果像上面解释的那样(所有发生),那么第一个示例的答案应该是1。@maraca,是的,我错过了。这是在一次访谈中被问到的,对于这两种情况,预期输出与我的样本输入中给出的相同。我对如何获得输出的理解不正确。@学习者您还在寻找答案吗?(请将我的目光从代码上移开,我希望您能简洁地描述如何从字符直方图获得真值替换匹配。)
private static Predicate<String> getPredicate(String s) {
    Map<Character, Integer> sMap = getMap(s);
    Predicate<String> p = s1 -> {
        Map<Character, Integer> s1Map = getMap(s1);
        Map<Character, Integer> sMapCopy = getMap(s);

        for (Map.Entry<Character, Integer> kvp : sMap.entrySet()) {
            if (s1Map.containsKey(kvp.getKey())) {
                if (s1Map.get(kvp.getKey()) < kvp.getValue()) {
                    sMapCopy.put(kvp.getKey(), kvp.getValue() - s1Map.get(kvp.getKey()));
                    s1Map.remove(kvp.getKey());
                } else if (kvp.getValue() < s1Map.get(kvp.getKey())) {
                    s1Map.put(kvp.getKey(), s1Map.get(kvp.getKey()) - kvp.getValue());
                    sMapCopy.remove(kvp.getKey());
                } else {
                    sMapCopy.remove(kvp.getKey());
                    s1Map.remove(kvp.getKey());
                }
            }
        }

        boolean result = sMapCopy.size() == 1 && s1Map.size() == 1;
        if (result) {
            for (Map.Entry<Character, Integer> kvp : sMapCopy.entrySet()) {
                for (Map.Entry<Character, Integer> kvp1 : s1Map.entrySet()) {
                    System.out.println(s + " and " + s1 + " can be replaced. Replace " + kvp.getValue() + " instances of " + kvp.getKey() + " with " + kvp1.getValue() + " instances of " + kvp1.getKey());
                }
            }
        } else {
            System.out.println(s + " and " + s1 + " cannot be replaced.");
        }
        return result;
    };

    return p;
}
String[] strings = {"aabbcdbbb", "aabbcdb", "aabbxdbb", "aabbbdbb", "aacccdcc", "ddbbcdbb", "eebbcdbb"};
long result = Arrays.stream(strings).filter(getPredicate("aabbcdbb")).count();
System.out.println("Replacables count: " + result);
aabbcdbb and aabbcdbbb cannot be replaced.
aabbcdbb and aabbcdb cannot be replaced.
aabbcdbb and aabbxdbb can be replaced. Replace 1 instances of c with 1 instances of x
aabbcdbb and aabbbdbb can be replaced. Replace 1 instances of c with 1 instances of b
aabbcdbb and aacccdcc can be replaced. Replace 4 instances of b with 4 instances of c
aabbcdbb and ddbbcdbb can be replaced. Replace 2 instances of a with 2 instances of d
aabbcdbb and eebbcdbb can be replaced. Replace 2 instances of a with 2 instances of e
Replacables count: 5