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