String 有效地计算包含所有元音的字符串对

String 有效地计算包含所有元音的字符串对,string,String,我已经解决了以下问题,但仍然需要改进性能: 我有很多话要说。对于每个有效的i,单词i由一个 仅包含小写元音的字符串Di,即字符“a”、“e”, “我”、“你”、“你” 无序的单词对的总数是多少 连在一起,它们包含所有元音 我的C++代码使用一个位数组来表示一个词中的元音。然后我通过组合它们的位数组来检查所有的字符串对,看看是否所有的元音位都设置好了。我通过将组合与一个位数组“complete”进行比较来实现这一点,该数组具有与元音对应的所有位: #include<bits/stdc++.h

我已经解决了以下问题,但仍然需要改进性能:

我有很多话要说。对于每个有效的i,单词i由一个 仅包含小写元音的字符串Di,即字符“a”、“e”, “我”、“你”、“你”

无序的单词对的总数是多少 连在一起,它们包含所有元音

<>我的C++代码使用一个位数组来表示一个词中的元音。然后我通过组合它们的位数组来检查所有的字符串对,看看是否所有的元音位都设置好了。我通过将组合与一个位数组“complete”进行比较来实现这一点,该数组具有与元音对应的所有位:

#include<bits/stdc++.h>
using namespace std;

int main()
{
  int t;
  cin>>t;      // number of different test cases
  while(t--)
  {
    int n;         // number of strings 
    cin>>n;

    int con_s[n];
    for(int i=0;i<n;i++)
    {
      string s;
      cin>>s;
      con_s[i]=0;      // converting vowels present in string into a bit array 
      for(int j=0;j<s.length();j++)
      {
        con_s[i] = con_s[i] | (1<<(s[j]-'a'));
      }
    }
    int complete = 0; // bit array corresponding to all possible vowels 
    complete = (1<<('a'-'a')) | (1<<('e'-'a')) | (1<<('i'-'a')) | (1<<('o'-'a')) | (1<<('u'-'a'));
    // cout<<complete;
    int count = 0;
    for(int i=0;i<n-1;i++)        // check the pairs
    {
      for(int j=i+1;j<n;j++)
      {
        if((con_s[i] | con_s[j])==complete)count++;
      }
    }
    cout<<count<<"\n";
  }
  return 0;
}
说明: 连接时,2对1和2以及2和3包含所有5个元音,而对1和3不符合标准,因为连接不包含“u”。因此,结果是2

限制条件:

1≤T≤1,000
1≤N≤105
1≤|Di|≤1,000 for each valid i
the sum of all |D_i| over all test cases does not exceed 3⋅107

假设有大量字符串。您的算法将比较它们之间的所有字符串,这是一个可怕的迭代次数

根本改进: 新方法 构建一个映射,将一个有序的唯一元音字符串(例如ae)与一个包含这些唯一元音的所有字符串的列表相关联,无论重复次数和顺序如何。例如:

ao -> aaooaoaooa, aoa, aaooaaooooooo  (3 words)
uie -> uiieieiieieuuu, uuuuiiiieeee   (2 words)
aeio -> aeioooeeiiaiei                (1 word)
当然,这有很多字符串,所以在代码中,您应该使用位图,而不是有序的唯一元音字符串。还请注意,您不希望生成组合字符串的列表,而只希望生成它们的计数。因此,您不需要所有字符串出现的列表,只需保持与位图匹配的字符串数:

16385 -> 3 
1048848 -> 2
16657 -> 1  
然后看看映射现有索引之间的成功组合,就像您所做的那样。对于一个大的字符串列表,您将拥有一个小得多的映射索引列表,因此这将是一个显著的改进

对于每个获胜的组合,将第一组字符串的大小乘以第二组字符串的大小以增加计数

16385 1048848 is complete -> 3 x 2 = 6 combinations
1048848 16657 is complete -> 2 x 1 = 2 combinations 
                                    ---
                                     8 potential combinations  
有什么改进? 这些组合是通过分析3x2位图发现的,而不是查看对应于唯一字符串的6x5位图。如果字符串的数量较多,则会获得相当数量级的增益


更一般地说,因为您有5个级别,并且必须至少有一个,所以最多只能有2个,这看起来像Hackerrank/Codechef/家庭作业。请分享你所做的代码并解释错误。相应地重新标记您的问题。不要在Python中发布C++代码,反之亦然。欢迎使用堆栈溢出!我们愿意帮助你。请花点时间把问题记下来,仔细阅读,然后相应地回答问题。请创建并提供示例输入、输出和您收到的错误消息(如果有)。这将帮助我们确定正在发生的事情,并提高您获得答案的机会。有多少效率是足够的?例如,您想在现代处理器上仅使用一个线程在1秒内处理100000个字符串吗?@DoeDoe注释部分用于注释,而不是答案。我是在评论这样一个事实:幼稚的解决方案在这些黑客银行或类似的网站上不起作用,你需要找到一种不同的方法。这些网站的全部目的是让你做研究,而不是找人为你做研究。你似乎专注于我的评论,但完全不知道为什么你会被多人否决,离问题结束还有两票。任何人都不应该在这里发布这个问题的答案,因为这将被视为作弊,完全违背其他网站的目的。从这里复制并粘贴答案到那里。伙计,我非常感谢你的解决方案,但如果单词单独包含所有元音,那么它就不起作用。你知道解决这个问题的方法吗?你能检查一下像3这样的测试用例吗:-aieoeiu,aiueoe,u等等@doe真的!mymap[complete]的字符串可以在它们之间组合。在这种情况下,您需要添加'mymap[complete]*mymap[complete]-1/2'@DoeDoe我已经相应地编辑了答案并更新了在线答案demo@Cristophe,你真是个传奇人物!。非常感谢!。我多亏了你,我今天学会了一个新把戏:
16385 1048848 is complete -> 3 x 2 = 6 combinations
1048848 16657 is complete -> 2 x 1 = 2 combinations 
                                    ---
                                     8 potential combinations  
map<int, int> mymap; 
int n;
cin>>n;

for(int i=0;i<n;i++) {
    string s;
    cin>>s;
    int bm=0;
    for(int j=0;j<s.length();j++)
        bm |= (1<<(s[j]-'a'));
    mymap[bm]++;
}
int complete = (1<<('a'-'a')) | (1<<('e'-'a')) | (1<<('i'-'a')) | (1<<('o'-'a')) | (1<<('u'-'a'));
int count = 0;
int comparisons = 0; 
for (auto i=mymap.begin(); i!=mymap.end(); i++)  {
    auto j=i; 
    for(++j;j!=mymap.end();j++) {
        comparisons++; 
        if((i->first | j->first)==complete) {
            count += i->second * j->second; 
            cout << i->first <<" "<<j->first<<" :"<<i->second<<" "<<j->second<<endl;
        }
    }
}
auto special = mymap.find(complete);  // special case: all strings having all letters
if (special!=mymap.end()) {           // can be combined with themselves as well
    count += special->second * (special->second -1) / 2; 
}
cout<<"Result: "<<count<<" (found in "<<comparisons<<" comparisons)\n";