「アルゴリズムノート」学習日記-6.4マップの一般的な使用法の詳細

6.4マップの一般的な使用法の詳細な説明

コードアップコンテストID:100000599

質問A:音声パターン(25)

描目描述
人々はしばしば同じ言葉の同義語の中で好みを持っています。たとえば、「警察」を好む人もいれば、「警官」を好む人もいます。このようなパターンを分析すると、話者のIDを絞り込むのに役立ちます。これは、たとえば、オンラインアバターの背後にいる同じ人物かどうかを検証するときに役立ちます。
ここで、誰かのスピーチからサンプリングされたテキストの段落を指定すると、その人の最も一般的に使用される単語を見つけることができますか?
输入力
各入力ファイルには、1つのテストケースが含まれています。いずれの場合も、1行のテキストは1048576文字以下で、改行 '\ n'で終了します。入力は、少なくとも一つの英数文字、すなわち、セット[0-9 AZ AZ]から1つの文字が含まれています。
输出
各テストケースについて、入力テキストで最も一般的に出現する単語を1行に出力し、その後にスペースと入力で出現した回数を続けます。そのような単語が複数ある場合は、辞書順で最小の単語を印刷します。単語はすべて小文字で印刷する必要があります。ここで「単語」とは、英数字以外の文字または行の先頭/末尾で区切られた英数字の連続したシーケンスとして定義されます。
言葉はケースであることに注意してください小文字を区別しない
样例输入

Can1: "Can a can can a can?  It can!"

出力例

can 5

アイデアは、
一般的に、この問題は言葉の数は大文字と小文字を区別しないときに最も頻繁に発生する単語の内側にあなたの単語数(ここでは単語が二重引用符の内容が文字列の内容全体ではないことに注意してください)を作成することであることを意味します、しかし、出力時には単語は小文字である必要があり、同じ回数の単語が複数ある場合は、最小の辞書式順序の単語が出力されます。

この質問は明らかにハッシュマッピングの関係を確立する必要があります。出力コンテンツが最大の添え字と値である限り、文に現れるすべての単語を添え字として、内容を出現回数として使用できると想像してください。答えです。整数ハッシュに対応する文字列の前に、10進数で26から10の方法を使用しました。ハッシュ関数の記述方法を忘れた場合は、mapを使用してそれを行うことができます(これはこの質問のように)より便利です〜

明らかに、stringとintの間のマッピングを確立する必要があるため、各単語を取得する方法(タイトルの単語の定義は、サンプルのCan1のように、連続した文字と数字の文字列です)、I Liu Shenのアイデアを参考に、非常に便利なC標準ライブラリ<ctype.h>(または<cctype>)のisalnum()関数(文字か数字かを判別する)とtolower()関数(小文字)を使用します。このライブラリには多くの関数があります。詳細については、新人チュートリアルをご覧ください。

C標準ライブラリ-<ctype.h>

実際、このライブラリとその中の主要な関数の使用法がわかっている場合、この質問は非常に簡単です。文字列の各ビットが最初から文字または数値のどちらであるかを判別するだけです。そうである場合は、一時文字列tmp(文字列+ =操作を追加すると、文字列と文字列を接続できます)、次の桁が文字または数値でなくなるまで、マップの値に1を追加します(mp [tmp] ++) 、次の単語を連結する準備をするために使用される一時的な文字列tmpを空にします。

上記の操作はほとんどのサンプルで問題ありませんが、Codeupは間違った83を答え、PATも23ポイントです(最後のサンプルはポイントを通過できません)。ただし、これは大きな問題ではありません。もちろん、慎重に見つけることができます。

入力には、少なくとも1つの英数字、つまりセット[0-9 AZ az]の1文字が含まれています。

重要なメッセージをご覧ください。少なくとも1つの英数字つまり、最後の例では、数字1のみ、または文字aのみを入力する可能性があります。その場合、上記の判断方法では、次の桁が文字と数字でなくなるまで mp [tmp] ++は実行されません。、文字列tmpの操作をクリアします。ここに英数字のみを入力した場合、次の桁が英数字ではないということはないため、マップ内でマッピング関係はまったく確立されません。

したがって、文字列の最後の数字がアルファベット文字でないかどうかを特別に判断する必要があります。それでもアルファベット文字である場合は、mp [tmp] ++を接続し、今回tmpが接続された直後に文字列をクリアします。ループが終了した場合、マップに挿入する必要のある単語は既に配置されています。

さらに、最大値を探すときは、イテレーター割り当て構文を使用しないことをお勧めします。最初にイテレーターtempを宣言し、次に最大値が更新されるたびに、現在のイテレーターがtempに割り当てられ、最後にtempと同じ長さ-> firstとtemp-> secondは、最大値に対応するキーと値を取得できます。最初のいくつかのテストポイントのため、この構文が問題ありませんが、最終的にテストポイントが発生しますミス Codeupの上、である、実行エラーをしたがって、さまざまな国境を越えた問題を回避するために、キーと値に対応する2つの変数を宣言して、最大値に対応するキーと値を格納するようにしてください。
コード

#include<cstdio>
#include<cctype>
#include<string.h>
#include<algorithm>
#include<map>
#include<string>
#include<iostream>
using namespace std;
map<string, int> mp;
int main(){
	string a;
	while(getline(cin, a)){//想要用cin读入空格需要用getline(C语言中是gets) 
		string tmp;
		for(int i=0;i<a.length();i++){
			if(isalnum(a[i])&&i!=a.length()-1){//如果当前位是字母和数字且不是最后一位 
				a[i] = tolower(a[i]);//转换为小写 
				tmp += a[i];//给tmp串上当前字符 
				continue;//继续下一轮循环 
			}
			if(isalnum(a[i])&&i==a.length()-1){//如果最后一位还是字母和数字 
				a[i] = tolower(a[i]);
				tmp += a[i];
				mp[tmp]++;
				tmp.clear();
			} 
			if(tmp.length()!=0){//如果tmp不为空(这里是为了防止下一次还是非字母数字时,执行mp[tmp]++的操作)
				mp[tmp]++;
				tmp.clear();	
			}
		}
		int max = 0;
		string keymax;
		for(map<string, int>::iterator it = mp.begin();it!=mp.end();it++){
			if(it->second>max){//如果键的值大,则更新max的值 
				keymax = it->first;
				max = it->second;
			}
		}
		cout<<keymax<<" "<<max<<endl;
		mp.clear();
	}
	return 0;
}

まとめ

この質問の最大の難しさは、Cライブラリ関数isalnum()の使用法を考えることだと思います。この関数がわからない場合は、1つずつ調べて単語(および小文字)を見つけて、ここで思い出させてください。Own:マップを使用するこの種のトピックの場合、連結操作を実行する一時的な文字列tmpを宣言し、連結後にマップに直接配置することができます。最初にすべての単語を削除し、次に別の単語を削除することを考えました1つはマップに配置されます。これは明らかに少し愚かな操作です_(:з∠)_

したがって、ここでは、何も実行していないときにCおよびC ++の標準ライブラリを確認することをお勧めします。使用できる非常に便利な妖精関数(昨日の前日のセットには、実際には交差セットのカプセル化関数があるなど)を見つけたかもしれません。

一般に、mapはハッシュマッピングに適したコンテナを提供しますが、通常、mapで解決できる文字または文字列に対応する整数の問題が発生し、スペースを節約し、簡潔になります。コード。

元の記事を公開54件 受賞27件 ビュー4987件

おすすめ

転載: blog.csdn.net/weixin_42257812/article/details/105286173