0

For a given number of test cases, we are given an integer n where n is the number of strings and we have to find a number of common elements (elements which are present in each one of the strings).and length of strings can be upto 200,and a character(lower case) can be there multiple times in string.

For example (one test case, three strings in the test case):

2
3
Weeb
Hello
Anime

4

llana
allon
mellon 
gallon

OUTPUT [ first test case ]= 1 (as we can see "e" is common in all strings).

[ second test case ] = 2 (as we can se "l" && "n" are common in all strings).

I have tried to make an array of strings and compare them but I could not get any answer. my code

#include <iostream>
#include<string>
#include<cstdio>

using namespace std;

int main(){
    int t;
    cin>>t;
   while(t--){
       int n,i,j,k,count=0;    
       cin>>n;
       string a[1000];

       for(i=0;i<n;i++)
        cin>>a[i];
       for(i=0;i<n;i++){
        for(j=0;j<4;j++){
         for(int k=0;k<4;k++){

         if(a[i][j]==a[i+1][k])           
            a[i][j]=a[i+1][k];

         else            
           a[i][j]=NULL;

        }
    }

  }

  for(i=0;a[i]!='\0';i++)
       count++;

   }

   cout<< count << endl;
   return 0;

 }
Black Hawk
  • 21
  • 5
  • 6
    " I have tried to make an array of strings and compare them" Okay... then post the code you have so far and explain the problem you have – 4386427 Feb 02 '19 at 07:46
  • 1
    Welcome to Stack Overflow. Please read the [About] and [Ask] pages. We'll help you fix an honest attempt to solve the problem, but we won't write the code for you. Note that the answer for C++ won't be usable in C, and the answer in C shouldn't be used in C++ — so I've removed the C++ tag, leaving the C tag. The problem was never mathematical; at most, it involves arithmetic (basic counting). How long can the strings be? – Jonathan Leffler Feb 02 '19 at 07:58
  • How about making an array for all characters (there are only 256 possible values for `char`) and set bit 0 (1) if a character occurs in first string, bit 1 (2) if in second string, bit 2 (4) if in third and so on. This is, of course, limited to the number of bits of the element type of this array but might be sufficient. (E.g. Using `std::uint32_t` as array element type would make the limit 32.) A character appears in all strings if it has all possible bits set according to your number of strings. Bit i for index i can be determined easily with bit shift (`operator< – Scheff's Cat Feb 02 '19 at 08:04
  • @Scheff This question is tagged C, not C++; there are no namespaces in C. You'd want `uint32_t`, not `std::uint32_t`. – aaaaaa123456789 Feb 02 '19 at 08:28
  • @aaaaaa123456789 Yeah. I see. Though, the C++ tag has been removed - probably while or after I wrote my comment. (I looked for C++ questions. That's why I think it was not my fault.) However, considering your correction, it should work in C as well. (And, I thought about alternative approaches using `std::set` and intersection but that's not a solution anymore...) ;-) – Scheff's Cat Feb 02 '19 at 08:30
  • What does the `4` in the source code mean, where does it come from? And `if(a[i][j]==a[i+1][k]) a[i][j]=a[i+1][k];` seems to assign a value just checked to already be at the destination. – greybeard Feb 02 '19 at 13:16
  • @Black Hack, If I am not wrong, this is same question of an ongoing contest. Although you rephrased it but I am sure. And if I am not wrong it is unfair to ask a question about an ongoing contest. – Brij Raj Kishore Feb 02 '19 at 13:20

2 Answers2

0

how i focus it: the ABC has 26 letters. Create an array with 26 positions, take the first word(String) and analyze the letters one by one. Add each letter sort from A to Z to the array position as a sum to his value 1, at the end, search the highest one.

example:

String = HA String = HAA

ABZ[7] = 2 ABZ[0] = 3

Result Pos 0 = 3 = A

:)

  • for given strin=HA and STRING=HAA, answer is 1 because A is common, it dosent matter how many time it occurs – Black Hawk Feb 02 '19 at 09:41
0

I must admit that I didn't fully understand the solution presented in the self-answer of OP. This encouraged me to present a different one.

The general idea is to apply set operations to the individual strings.

All characters of first string are possible candidates to be common. For each other string, if a character of first is not in other string then it is removed from first string. (i.e. a set intersection) Finally, the left characters in first string are that which are common with all other strings.

To make set operations in C++, I could have stored each string in a std::set to perform std::set_intersection() afterwards.

Instead, I applied std::sort() to the first string. The string might have duplicated characters. These are removed by a succeeding call of std::unique().

The other strings (2nd, 3rd, etc.) are sorted as well. The call of std::unique() isn't necessary because the following intersection won't consider any duplicate in the second string as there will never be one in the first string.

For the intersection, I recalled an older answer of mine (to SO: how to find the intersection of two std::set in C++?). I considered to use std::set_intersection() but IMHO it might not store the result into the range it's reading from. I also didn't want another string copy for each iteration and, hence, used an alternative implementation intersection() instead.

This is what I got:

#include <algorithm>
#include <iostream>
#include <string>
#include <vector>

void intersection(std::string &first, const std::string &second)
{
  std::string::iterator iter1 = first.begin();
  for (std::string::const_iterator iter2 = second.begin();
    iter1 != first.end() && iter2 != second.end();) {
    if (*iter1 < *iter2) iter1 = first.erase(iter1);
    else {
      if (!(*iter2 < *iter1)) ++iter1;
      ++iter2;
    }
  }
  first.erase(iter1, first.end());
}

size_t check(const std::vector<std::string> &sample)
{
  // check trivial case (sample empty)
  if (sample.empty()) return 0;
  std::string first = sample[0];
  // sort string characters by their values  
  std::sort(first.begin(), first.end());
  // remove duplicates
  std::string::iterator end = std::unique(first.begin(), first.end());
  first.erase(end, first.end());
  // check the other strings agains first
  for (size_t i = 1, n = sample.size(); i < n; ++i) {
    std::string other = sample[i];
    std::sort(other.begin(), other.end());
    intersection(first, other);
  }
#if 1 // set 0 to disable diagnostics
  // diagnostics
  std::cout << '"' << first << "\" ";
#endif // 1
  return first.size();
}

int main()
{
  std::vector<std::string> samples[] = {
    { "Weeb", "Hello", "Anime" },
    { "llana", "allon", "mellon", "gallon" }
  };
  // check samples
  for (const std::vector<std::string> &sample : samples) {
    // print input
    std::cout << "check(";
    const char *sep = "";
    for (const std::string &word : sample) {
      std::cout << sep << '"' << word << '"';
      sep = ", ";
    }
    std::cout << "):\n";
    // print common characters
    std::cout << "  Common characters: " << check(sample) << '\n';
  }
  return 0;
}

Output:

check("Weeb", "Hello", "Anime"):
  Common characters: "e" 1
check("llana", "allon", "mellon", "gallon"):
  Common characters: "ln" 2

Live Demo on coliru

Notes:

  1. The algorithm doesn't distinguish between letters and any other character. It would work for digits and special characters (and any other character) as well.

  2. According to the previous fact, the algorithm does distinguish lowercase and uppercase letters. I'm not sure whether or not OP intended this nor if OP is aware about this. I found it legal to make it this way if there is no explicit constraint concerning this. (And, it takes off the burden of any concerns regarding encoding, internationalization, and such.)

Scheff's Cat
  • 16,517
  • 5
  • 25
  • 45