【UKIEPC2015 C】【STL set map stringstream】Conversation Log 网络审查 被所有人都说过的话 map套set法+人哈希法

来源:互联网 发布:java array 找众数 编辑:程序博客网 时间:2024/05/29 11:43

map套set法:

#include<stdio.h> #include<iostream>#include<string.h>#include<vector>#include<sstream>#include<algorithm>#include<map>#include<set>using namespace std;const int N=1e4+5;const int L=2e6+10;set<string>name;//记录所有人名map<string,set<string> >cnt;//记录说过每句话的所有人名map<string,int>freq;//记录每句话被说过的总次数map<string,int>::iterator it;char nm[24];char s[L];char w[L];int n,m;vector<pair<int,string> >b;int main(){    scanf("%d",&m);    for(int i=1;i<=m;i++)    {        //步骤一,读入这个人的名称        scanf("%s",nm);name.insert(nm);//步骤二,用stringstream处理他说过的所有话        gets(s);        stringstream cinn(s);        while(cinn>>w)//w是一句话        {            freq[w]++;//首先这句话的频率增加            cnt[w].insert(nm);//然后记录所有说过这句话的人        }    }//步骤三,查询所有话,找到被所有人说过的话,按照(被说过的次数降序,字典序升序)构建pair并且排序输出n=name.size();    for(it=freq.begin();it!=freq.end();it++)    {        if(cnt[it->first].size()==n)        {            b.push_back(make_pair(-it->second,it->first));        }    }    sort(b.begin(),b.end());    int g=b.size();    if(g==0)puts("ALL CLEAR");    else for(int i=0;i<g;i++)cout<<b[i].second<<endl;    return 0;}/*【trick&&吐槽】1,读题一定要认真。脑补题意很有可能会出问题的2,数组不能开小。人数最多1e4,话数可能达到1e6【题意】有m(1e4)行信息,所有信息的总长度2e6对于每行信息,第一个单词是说话者的名字,长度不超过20。接下来是这个说话者说过的所有单词。我们要说出被所有说话者都说过的单词。按照(单词使用频率,同频率下字典序)排列。如果不存在这样的单词,输出ALL CLEAR【类型】STL【分析】首先,人名是有用的。因为被所有人都说过的单词,才可能是答案的备选单词。我们怎么得到一个单词是否被所有人都使用过呢?做法一:对于每个单词,建立一个map<string,set<string> >,用set存这个单词被说过的人的名字建立一个map<string,int>,存这个单词被说过的次数这样我们只要统计最后有多少个人说过话(记做n),判定其set.size()是否恰好为n,就能得到这个单词是否被所有人使用过。这里有一个可以优化的地方,就是先把单词名hash成一个int,然后对一个int再展开第二维度。做法二:对于每个单词,建立一个map<string,int>存说过这个单词的人的个数建立一个map<string,int>空间,存这个单词被说过的次数这个与做法一不同的是,我们要如何维护说过这个单词的人的个数?可以以人为关键点。存每个人所说过的单词。对于一个人第一次说某个单词,那么说这个单词的人的个数+1。附上官方题解:https://docs.google.com/presentation/d/1V4UHi1pLUhZR32H06SlIMi9egm9acbQe-DNCLpAQmf8/present?slide=id.gc6f83aa91_0_56【时间复杂度&&优化】复杂度其实也就是nlog(n)级别的。总的set/map size大小不会超过n,【数据】input8Jepson no no no no nobody neverAshley why ever notMarcus no not never nobodyBazza no never know nobodyHatty why no nobodyHatty nobody never know why nobodyJepson never no nobodyAshley never never nobody nooutputnonobodyneverinput2Villain avastScoundrel ahoyoutputALL CLEAR*/

人哈希法:

#include<stdio.h> #include<iostream>#include<string.h>#include<vector>#include<sstream>#include<algorithm>#include<map>#include<set>using namespace std;const int N=1e4+5;const int L=2e6+10;map<string,int>name;//给每个人的名字做编号set<string>a[N];//记录每个人说过哪些话map<string,int>cnt;//记录每句话被多少人说过map<string,int>freq;//记录每句话被说过的总次数map<string,int>::iterator it;char nm[24];char s[L];char w[L];int n,m;vector<pair<int,string> >b;int main(){    n=0;scanf("%d",&m);    for(int i=1;i<=m;i++)    {        //步骤一,映射得到这个人的编号        scanf("%s",nm);        int o;        if(name.find(nm)==name.end())o=name[nm]=++n;        else o=name[nm];//步骤二,用stringstream处理他说过的所有话        gets(s);        stringstream cinn(s);        while(cinn>>w)//w是一句话        {            freq[w]++;//首先这句话的频率增加            if(a[o].find(w)==a[o].end())//个人说如果之前没说过这句话            {                cnt[w]++;//这句话说的人数++a[o].insert(w);//并且insert这句话            }        }    }//步骤三查询所有话,找到被所有人说过的话,按照(被说过的次数降序,字典序升序)构建pair并且排序输出    for(it=cnt.begin();it!=cnt.end();it++)    {        if(it->second==n)        {            b.push_back(make_pair(-freq[it->first],it->first));        }    }    sort(b.begin(),b.end());    int g=b.size();    if(g==0)puts("ALL CLEAR");    else for(int i=0;i<g;i++)cout<<b[i].second<<endl;    return 0;}/*【trick&&吐槽】1,读题一定要认真。脑补题意很有可能会出问题的2,数组不能开小。人数最多1e4,话数可能达到1e6【题意】有m(1e4)行信息,所有信息的总长度2e6对于每行信息,第一个单词是说话者的名字,长度不超过20。接下来是这个说话者说过的所有单词。我们要说出被所有说话者都说过的单词。按照(单词使用频率,同频率下字典序)排列。如果不存在这样的单词,输出ALL CLEAR【类型】STL【分析】首先,人名是有用的。因为被所有人都说过的单词,才可能是答案的备选单词。我们怎么得到一个单词是否被所有人都使用过呢?做法一:对于每个单词,建立一个map<string,set<string> >,用set存这个单词被说过的人的名字建立一个map<string,int>,存这个单词被说过的次数这样我们只要统计最后有多少个人说过话(记做n),判定其set.size()是否恰好为n,就能得到这个单词是否被所有人使用过。这里有一个可以优化的地方,就是先把单词名hash成一个int,然后对一个int再展开第二维度。做法二:对于每个单词,建立一个map<string,int>存说过这个单词的人的个数建立一个map<string,int>空间,存这个单词被说过的次数这个与做法一不同的是,我们要如何维护说过这个单词的人的个数?可以以人为关键点。存每个人所说过的单词。对于一个人第一次说某个单词,那么说这个单词的人的个数+1。附上官方题解:https://docs.google.com/presentation/d/1V4UHi1pLUhZR32H06SlIMi9egm9acbQe-DNCLpAQmf8/present?slide=id.gc6f83aa91_0_56【时间复杂度&&优化】复杂度其实也就是nlog(n)级别的。总的set/map size大小不会超过n,【数据】8Jepson no no no no nobody neverAshley why ever notMarcus no not never nobodyBazza no never know nobodyHatty why no nobodyHatty nobody never know why nobodyJepson never no nobodyAshley never never nobody no8Jepson no no no no nobody neverAshley why ever notMarcus no not never nobodyBazza no never know nobody nobody nobody nobody nobody nobodyHatty why no nobodyHatty nobody never know why nobodyJepson never no nobodyAshley never never nobody no2Villain avastScoundrel ahoy*/



1 0
原创粉丝点击