C++ 从最近的K个单词中找出最频繁的单词

C++ 从最近的K个单词中找出最频繁的单词,c++,data-structures,stl,C++,Data Structures,Stl,我试图解决这个问题: 这个想法很简单,您的程序将继续从一个不断向您的程序输入新单词的流中读取,但由于存储空间有限,您的程序只能记住最新的K个单词。因此,当第(K+1)个单词到达时,程序会忘记第一个单词;当第(K+2)个单词到达时,程序会忘记第二个单词,依此类推 我们希望您在每次新单词出现时,都能在最新的K单词中找到最频繁的单词。我尝试使用map(作为哈希表)deque(维护输入流)来解决这个问题。下面是我的代码,我已经尝试过,但在某些情况下,它并没有给出预期的结果 #include <bi

我试图解决这个问题:

这个想法很简单,您的程序将继续从一个不断向您的程序输入新单词的流中读取,但由于存储空间有限,您的程序只能记住最新的K个单词。因此,当第(K+1)个单词到达时,程序会忘记第一个单词;当第(K+2)个单词到达时,程序会忘记第二个单词,依此类推

我们希望您在每次新单词出现时,都能在最新的
K
单词中找到最频繁的单词。我尝试使用map(作为哈希表)deque(维护输入流)来解决这个问题。下面是我的代码,我已经尝试过,但在某些情况下,它并没有给出预期的结果

#include <bits/stdc++.h>
#include <string>
using namespace std;
#define ps pair<string,int>
map<string,int>dir;
int lookup( string name)
{

    map<string,int>::iterator it;
    dir[name]+=1;
    it=dir.find(name);
    return it->second;
}
void update(string name)
{
    map<string,int>::iterator it;
    it=dir.find(name);
    if(it!=dir.end()&& it->second>=1)
    dir[name]-=1;
    else dir[name]=0;
}
string small(string s1,string s2)
{
    int l=min(s1.size(),s2.size());
    if(s1==s2)return s1;
    else
    {
        for(int i=0;i<l;i++)if(s1[i]>s2[i])return s2;
        return s1;
    }
}
int main() 
{
    ios_base::sync_with_stdio(false);
    int n,k;
    int tc,cs=0;
    cin >> tc;
    while(tc--){cout<<"Case "<<++cs<<":"<<endl;
    cin >> n >> k;
    string words;
    deque<ps>Q;
    deque<ps>::iterator it;
    Q.clear();
    dir.clear();
    int max =-1;
    string mf;
    while(n--)
    {
        cin>> words;
        if(Q.size()<k)
        {
            int c = lookup(words);
            Q.push_back(ps(words,c));
            it=Q.end()-1;
            if(it->second > max)
            {
                    max = it->second;
                    mf = it->first;
            }
            else if(max==it->second)
            {
                max = it->second;
                mf = small(mf,it->first);
            }
            cout <<mf<<" "<<max<<endl;
        }
        else
        {
            map<string,int>::iterator itm;
            if(Q.size() >= k)
            {
                it=Q.begin();
                update(it->first);
                itm=dir.find(it->first);
                if(itm->second>0)
                max-=1;
                Q.pop_front();
                int c = lookup(words);
                Q.push_back(ps(words,c));
                it=Q.end()-1;
                itm=dir.find(mf);
                if(it->second > itm->second)
                {
                    max = it->second;
                    mf = it->first;
                }
                else if(it->second == itm->second)
                {
                    max = it->second;
                    mf = small(itm->first,it->first);
                }
                cout <<mf<<" "<<max<<endl;
            }

        }
    }
    }
    return 0;
}
以下可能会有所帮助:

class Counter
{
public:
    Counter(std::size_t size) : max_size(size) {}

    void AddWord(const std::string& word)
    {
        if (words.size() == max_size) {
            auto it = counts.find(words.front());
            --it->second;
            if (it->second == 0) {
                counts.erase(it);
            }
            words.pop();
        }
        words.push(word);
        ++counts[word];
    }

    const std::pair<const std::string, std::size_t>& getMax() const
    {
        return *std::max_element(counts.begin(), counts.end(),
        [](const std::pair<const std::string, std::size_t>& lhs, const std::pair<const std::string, std::size_t>& rhs)
        {
            return std::tie(lhs.second, rhs.first) < std::tie(rhs.second, lhs.first);
        });
    }

private:
    std::size_t max_size;
    std::queue<std::string> words;
    std::map<std::string, std::size_t> counts;
};
类计数器
{
公众:
计数器(std::size\u t size):最大大小(size){
void AddWord(const std::string和word)
{
if(words.size()=最大大小){
auto it=counts.find(words.front());
--第二;
如果(它->秒==0){
计数。擦除(它);
}
words.pop();
}
推(字);
++计数[字];
}
常量std::pair&getMax()常量
{
return*std::max_元素(counts.begin()、counts.end(),
[](常数std::pair&lhs,常数std::pair&rhs)
{
返回标准::tie(左秒,右首)<标准::tie(右秒,左首);
});
}
私人:
标准尺寸:最大尺寸;
std::队列字;
地图计数;
};

我已经修改了Jarod42的解决方案,以便与g++4.3.2一起使用,但是这种方法 max_元素函数太慢。需要更快的算法

#include <algorithm>
#include <iostream>
#include <string>
#include <cstdio>
#include <map>
#include <queue>
using namespace std;

int max_size;
string words[100000];
map<string, size_t> counts;
int ifrontword,ilastword;

bool mycmp( pair<const string, size_t>& lhs,  pair<const string, size_t>& rhs){
  if (lhs.second==rhs.second) return rhs.first<lhs.first;
  else return lhs.second<rhs.second;
}
map<string, size_t>::iterator it;

void AddWord(string& word){    
  if (ilastword-ifrontword == max_size) {
    counts[words[ifrontword]]--;
    if (counts[words[ifrontword]]==0)
      counts.erase(words[ifrontword]);
    ifrontword++;
  }
  words[ilastword++]=word;
  counts[word]++;
}

pair<const string, size_t>& getMax() {
  return *max_element(counts.begin(), counts.end(), mycmp);
}

int main(){
  ios_base::sync_with_stdio(false);
  int n,k;
  int tc,cs=0;
  string word;
  scanf("%d",&tc);
  while(tc--){
    cout<<"Case "<<++cs<<":"<<endl;
    scanf("%d%d",&n,&k);
    max_size=k;
    counts.clear();
    ilastword=ifrontword=0;
    while(n--){
      cin>> word;
      AddWord(word);
      pair<const string, size_t> &p = getMax();
      cout << p.first << " " << p.second << endl;
    }
  }
  return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
int max_大小;
字符串[100000];
地图计数;
int-ifrontword,ilastword;
bool mycmp(成对和左侧、成对和右侧){

if(lhs.second==rhs.second)返回rhs.first基本思想:维护一个单词到计数的映射。还维护一个k大小的单词数组。输入新词时,检查数组的大小。如果数组已满,删除最旧的单词,下移元素,添加新元素;减少(现在已删除)的计数地图中最早的单词,增加地图中新单词的计数。在地图中打印具有最大值的单词。Continue@inspectorG4dget我也尝试过同样的想法,我用地图来存储单词及其出现频率,我用deque来存储单词,当它达到极限k时,我就删除了g使用旧单词,并通过降低频率再次维护映射。我正在做同样的事情,但得到了错误的答案。这里是问题链接[link],您不需要deque-一个最大大小的队列就足够了。我无法帮助您了解实现细节,因为我不具备C++中所需的专业知识“它有时做不到我想要的”。“当输入是XYZ时,输出是ABC,而我希望是IJK”。哪种措辞可能会吸引更多的答案?由你决定。
#include
不是标准,可能会阻止使用其他实现的潜在贡献者。更喜欢可移植代码。
#include <algorithm>
#include <iostream>
#include <string>
#include <cstdio>
#include <map>
#include <queue>
using namespace std;

int max_size;
string words[100000];
map<string, size_t> counts;
int ifrontword,ilastword;

bool mycmp( pair<const string, size_t>& lhs,  pair<const string, size_t>& rhs){
  if (lhs.second==rhs.second) return rhs.first<lhs.first;
  else return lhs.second<rhs.second;
}
map<string, size_t>::iterator it;

void AddWord(string& word){    
  if (ilastword-ifrontword == max_size) {
    counts[words[ifrontword]]--;
    if (counts[words[ifrontword]]==0)
      counts.erase(words[ifrontword]);
    ifrontword++;
  }
  words[ilastword++]=word;
  counts[word]++;
}

pair<const string, size_t>& getMax() {
  return *max_element(counts.begin(), counts.end(), mycmp);
}

int main(){
  ios_base::sync_with_stdio(false);
  int n,k;
  int tc,cs=0;
  string word;
  scanf("%d",&tc);
  while(tc--){
    cout<<"Case "<<++cs<<":"<<endl;
    scanf("%d%d",&n,&k);
    max_size=k;
    counts.clear();
    ilastword=ifrontword=0;
    while(n--){
      cin>> word;
      AddWord(word);
      pair<const string, size_t> &p = getMax();
      cout << p.first << " " << p.second << endl;
    }
  }
  return 0;
}