在给定的字符串集中找到一些公共字符?

时间:2019-02-02 07:45:00

标签: c++ algorithm

对于给定数量的测试用例,我们得到一个整数n,其中n是字符串的数量,我们必须找到许多公共元素(每个元素中都存在的元素)字符串的长度)。字符串的长度最多可以为200,字符串中的一个字符(小写)可以多次出现。

例如(一个测试用例,测试用例中的三个字符串):

2
3
Weeb
Hello
Anime

4

llana
allon
mellon 
gallon

OUTPUT [第一个测试用例] = 1(我们可以看到“ e”在所有字符串中都是通用的)。

[第二个测试用例] = 2(因为我们可以在所有字符串中看到“ l”和&“ n”。)

我试图制作一个字符串数组并进行比较,但是我没有任何答案。 我的代码

#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;

 }

2 个答案:

答案 0 :(得分:0)

我如何关注它:ABC有26个字母。创建一个具有26个位置的数组,获取第一个单词(字符串)并一个一个地分析字母。将从A到Z的每个字母排序加到数组位置,作为其值1的总和,最后搜索最高的一个字母。

示例:

字符串= HA 字符串= HAA

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

结果位0 = 3 = A

:)

答案 1 :(得分:0)

我必须承认我不完全了解self-answer of OP中提出的解决方案。 这鼓励我提出另一种建议。

通常的想法是将设置操作应用于单个字符串。

第一个字符串的所有字符都可能是相同的候选字符。对于其他字符串,如果first字符不在其他字符串中,则将其从第一个字符串中删除。 (即设定的交集)最后,第一个字符串中的左字符是所有其他字符串所共有的。

要在C ++中进行设置操作,我可以将每个字符串存储在std::set中,然后再执行std::set_intersection()

相反,我将std::sort()应用于了第一个字符串。该字符串可能包含重复的字符。后续调用std::unique()会将其删除。

其他字符串(2 nd ,3 rd 等)也进行了排序。不需要调用std::unique(),因为下面的交集不会考虑第二个字符串中的任何重复项,因为第一个字符串中永远不会有一个重复项。

对于交叉路口,我想起了我的一个较早答案(对SO: how to find the intersection of two std::set in C++?)。我考虑使用std::set_intersection(),但恕我直言,它可能不会将结果存储到其读取的范围内。我也不希望每次迭代都复制另一个字符串,因此,使用了替代实现intersection()

这就是我得到的:

#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;
}

输出:

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

Live Demo on coliru

注释:

  1. 该算法无法区分字母和其他任何字符。它也适用于数字和特殊字符(以及其他任何字符)。

  2. 根据先前的事实,算法可以区分小写字母和大写字母。我不确定OP是否打算这样做,或者OP是否知道这一点。如果没有明确的限制,我认为这样做是合法的。 (而且,它减轻了编码,国际化等方面的任何麻烦。)