简体   繁体   中英

Java - Counting how many characters show up in another string

I am comparing two strings, in Java, to see how many characters from the first string show up in the second string. The following is some expectations:

matchingChars("AC", "BA") → 1  
matchingChars("ABBA", "B") → 2  
matchingChars("B", "ABBA") → 1  

My approach is as follows:

 public int matchingChars(String str1, String str2) {

    int count = 0;

     for (int a = 0; a < str1.length(); a++)
    {    
        for (int b = 0; b < str2.length(); b++)

          {  char str1Char = str1.charAt(a);
             char str2Char = str2.charAt(b);

                if (str1Char == str2Char)
                   {   count++;
                       str1 =  str1.replace(str1Char, '0');
                   }
          }
    }
     return count; 
    }  

I know my approach is not the best, but I think it should do it. However, for

   matchingChars("ABBA", "B") → 2  

My code yields "1" instead of "2". Does anyone have any suggestion or advice? Thank you very much.

Assuming that comparing "AABBB" with "AAAABBBCCC" should return 15 (2*3 + 3*3 + 0*3) then:

For each string make a Map from the character of the string to the count of characters. Compute the intersection of the keysets for the two maps. For each element in the keyset accumulate the product of the values. Print the result. This is linear in the size of the two strings.

Is it ok to supply working code on homework problems?

public long testStringCount() {
  String a = "AABBBCCC";
  String b = "AAABBBDDDDD";

  Map<Character,Integer> aMap = mapIt(a);
  Map<Character,Integer> bMap = mapIt(b);

  Set<Character> chars = Sets.newHashSet(aMap.keySet());
  chars.addAll(bMap.keySet());

  long result = 0;
  for (Character c : chars) {
    Integer ac = aMap.get(c);
    Integer bc = bMap.get(c);
    if (null != ac && null != bc) {
     result += ac*bc;
    }
  }
  return result;
}

private Map<Character, Integer> mapIt(String a) {
 Map<Character,Integer> result = Maps.newHashMap();
 for (int i = 0; i < a.length(); i++) {
   Character c = a.charAt(i);
   Integer x = result.get(c);
   if (null == x) {
     x = 0;
   }
   x++;
   result.put(c, x);
 }
 return result;
}

显然,您必须确保只对字符串1中的唯一字符进行计数。对B两次计数是因为对B两次计数,对于字符串1中的每次出现一次。

Well your code is only showing 1 because of this line:

str1 =  str1.replace(str1Char, '0');

That's turning "ABBA" into "A00A" - so the second B doesn't get seen.

Perhaps you should turn the second string into a HashSet<Character> instead... then you could just use something like:

int count = 0;
for (int i = 0; i < str1.length; i++)
{
    if (otherSet.contains(str1.charAt(i))
    {
        count++;
    }
}

It's not clear what result you want to get from "ABBA" / "CBCB" - if it's 2 (because there are 2 Bs) then the above approach will work. If it's 4 (because each of the 2 Bs in the first string matches 2 Bs in the second string) then all you need to do is get rid of your replace call.

EDIT: With the clarifications, it sounds like you could just do this:

for (int a = 0; a < str1.length(); a++)
{    
    for (int b = 0; b < str2.length(); b++)
    {  
        if (str1.charAt(a) == str2.charAt(b))
        {
            count++;
            // Terminate the inner loop which is iterating over str2,
            // and move on to the next character in str1
            break;
        }
    }
}

Your solution works, but is quadratic. If all characters are below 256, then you can do something like this:

int matching(String s1, String s2) {
int[] count1 = frequencies(s1);
int[] count2 = frequencies(s2);
sum = 0;
for(int i =  0; i< 256; i++) {
    sum += count1[i]*count2[i] != 0 ? Math.max(count1[i], count2[i]) : 0;
}
return sum;
}

int[] frequencies(String s) {
int[] ret = new int[256];
for(char c : s) {
    int[c]+=1;
}
}

Otherwise, you'll need a multiset .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM