使用向量求解C++中的变位词

Using vectors to solve the anagrams in C++

本文关键字:C++ 向量      更新时间:2023-10-16

我有一个函数,它接收两个字符串向量,并比较每个元素,看看它们是否是彼此的变位符。

矢量#1:"bat"、"add"、"zyz"、"aaa"

矢量#2:"tab"、"dad"、"xyx"、"bbb"

限制和其他需要澄清的事项:函数应该循环通过两个向量并比较字符串。我只应该根据每个向量的索引进行比较;这意味着我只比较第一个索引中的字符串,然后比较第二个索引的字符串,依此类推。可以放心地假设,作为参数传入的向量总是相同的大小。

如果比较的字符串是变位符,则屏幕上会打印"匹配"。如果不是,则会打印"不匹配"。

输出:匹配不匹配不匹配

我在这个问题上陷入了荒谬的困境,我知道如何反转字符串,但到了这个地步,我就有点不知所措了。

我知道我需要迭代每个向量,然后进行比较。但是我怎样才能比较字符串中的每个字母呢?此外,我不允许包含任何其他内容,如算法、排序或集合。我试着深入研究了很多问题,但大多数答案都利用了这一点。

如果有什么技巧可以解决这个问题,那就太好了。我很快就会发布我的发现。

到目前为止,我得到的是:

#include <iostream>
#include <vector>
#include <string>
using namespace std;
void anagrams(const vector<string>& vOne, const vector<string>& vTwo){
for(int i=0; i< vOne.size(); i++){
    for(int j=0; j< vTwo.size(); j++){
        if(vOne[i].size() != vTwo[j].size()){
            cout << 0 << endl;
        }
        else {
            cout << 1 << endl;
        }
    }
  }
}
void quicksort(vector<int>& a, int low, int high){
    if(low < high)
    {
        int mid = (low + high)/2;
        int pivot = a[mid];
        swap(a[high], a[mid]);
        int i, j;
        for(i=low, j=high-1; ;){
            while(a[i]<pivot) ++i;
            while(j>i && pivot < a[j]) --j;
            if (i < j)
                swap(a[i++], a[j--]);
            else
                break;
        }
        swap(a[i], a[high]);
    } 
    quicksort(a, low, i - 1);
    quicksort(a, i + 1, high);
}

提前感谢!

虽然您不能使用排序,但您仍然应该对要检查的单词进行排序,看看它们是否是变位符。您只需要手动对char[]进行排序,这很不幸,但却是一个很好的练习。我会做一个谓词,一个比较两个字符串并返回true或false的函数,并用它来检查它们是否是变位词。此外,似乎你不需要打印出两个实际匹配的单词,如果这是真的,那么你可以在第一次读入时对向量中的单词进行排序,然后通过谓词函数运行它们。

// Predicate
bool isMatch(const string &lhs, const string &rhs)
{
    ...sort and return lhs == rhs;
}

如果你写这个函数,就像我上面提到的那样,你通过const引用传递参数,然后你可以将参数复制到char[]中(由于存在漏洞,不使用strcpy())并对单词进行排序。我建议将你的排序作为自己的函数来编写。另一个提示是,记住事情要快得多,stl使用智能ptr进行排序。不管怎样,我希望这能帮上一点忙,我不想给你答案。

只要字符串只包含A-z和A-z之间的字符,那么一个相当快速的解决方案就是

bool is_anagram( const string& s1, const string& s2 ) {
    if( s1.size() != s2.size() ) {
        return false;
    }
    size_t count[ 26 * 2 ] = { 0 };
    for( size_t i = 0; i < s1.size(); i++ ) {
        char c1 = s1[ i ];
        char c2 = s2[ i ];
        if( c1 >= 'a' ) {
            count[ c1 - 'a' ]++;
        }
        else {
             count[ c1 - 'A' + 26 ]++;
        }
        if( c2 >= 'a' ) {
            count[ c2 - 'a' ]--;
        }
        else {
             count[ c2 - 'A' + 26 ]--;
        }
    }
    for( size_t i = 0; i < 26 * 2; i++ ) {
        if( count[ i ] != 0 ) {
            return false;
        }
    }
    return true;
}

如果您愿意使用C++11,这里有一些效率相当低的代码,用于查看两个字符串是否为变位符。我让你循环浏览单词表。

#include <iostream>
#include <vector>
using namespace std;
int count_occurrences(string& word, char search) {
    int count = 0;
    for (char s : word) {
        if (s == search) {
            count++;
        }
    }
    return count;
}
bool compare_strings(string word1, string v2) {       
    if (word1.size() != v2.size())
    {
        return false;
    }    
    for (char s: word1) //In case v1 contains letters that are not in v2
    {
        if (count_occurrences(word1, s) != count_occurrences(v2, s))
        {
            return false;
        }
    }        
    return true;
}
int main() {
    string s1 = "bat";
    string s2 = "atb";
    bool result = compare_strings(s1, s2);
    if (result)
    {
        cout << "Match" << endl;
    }
    else
    {
        cout << "No match" << endl;
    }
}

这是通过简单地计算给定字母在字符串中出现的次数来实现的。更好的方法是按字母顺序对字符串中的字符进行排序,然后比较排序后的字符串,看看它们是否相等。我将由你来改进这一点。

致以最良好的祝愿。

另一个解决方案,因为我已经厌倦了:

#include <iostream>
#include <vector>
#include <string>
int equiv_class(char c) {
   if ((c>='A')&&(c<='Z')) return c-'A';
   if ((c>='a')&&(c<='z')) return c-'a';
   return 27;
}
bool is_anagram(const std::string& a, const std::string& b)
{
   if (a.size()!=b.size()) return false;
   int hist[26]={};
   int nz=0; // Non-zero histogram sum tally
   for (int i=0, e=a.size() ; i!=e ; ++i)
   {
      int aclass = equiv_class(a[i]);
      int bclass = equiv_class(b[i]);
      if (aclass<27) {
         switch (++hist[aclass]) {
         case 1: ++nz; break; // We were 0, now we're not--add
         case 0: --nz; break; // We were't, now we are--subtract
         // otherwise no change in nonzero count
         }
      }
      if (bclass<27) {
         switch (--hist[bclass]) {
         case -1: ++nz; break; // We were 0, now we're not--add
         case  0: --nz; break; // We weren't, now we are--subtract
         // otherwise no change in nonzero count
         }
      }
   }
   return 0==nz;
}
int main()
{
   std::vector<std::string> v1{"elvis","coagulate","intoxicate","a frontal lobotomy"};
   std::vector<std::string> v2{"lives","catalogue","excitation","bottlein frontofme"};
   for (int i=0, e=(v1.size()==v2.size()?v1.size():0); i!=e; ++i) {
      if (is_anagram(v1[i],v2[i])) {
         std::cout << " Match";
      } else {
         std::cout << " No Match";
      }
   }
}