#include <map>
#include <iostream>
#include <string>
#include <vector>
#include <set>

#include "split.h"

using std::cin;            using std::cout;
using std::endl;           using std::getline;
using std::istream;        using std::string;
using std::vector;         using std::map;
using std::set;

// find all the lines that refer to each word in the input
map<string, set<int> >
	xref(istream& in,
	     vector<string> find_words(const string&) = split)
{
	string line;
	int line_number = 0;
	map<string, set<int> > ret;

	// read the next line
	while (getline(in, line)) {
		++line_number;

		// break the input line into words
		vector<string> words = find_words(line);

		// remember that each word occurs on the current line
#ifdef _MSC_VER
		for (std::vector<string>::const_iterator it = words.begin();
#else
		for (vector<string>::const_iterator it = words.begin();
#endif
		     it != words.end(); ++it)
			ret[*it].insert(line_number);
	}
	return ret;
}

int main()
{
	// call `xref' using `split' by default
	map<string, set<int> > ret = xref(cin);

	// write the results
#ifdef _MSC_VER
	for (std::map<string, set<int> >::const_iterator it = ret.begin();
#else
	for (map<string, set<int> >::const_iterator it = ret.begin();
#endif
	     it != ret.end(); ++it) {
		// write the word
		cout << it->first << " occurs on line(s): ";

		// followed by one or more line numbers
#ifdef _MSC_VER
		std::set<int>::const_iterator line_it = it->second.begin();
#else
		set<int>::const_iterator line_it = it->second.begin();
#endif
		cout << *line_it;	// write the first line number

		++line_it;
		// write the rest of the line numbers, if any
		while (line_it != it->second.end()) {
			cout << ", " << *line_it;
			++line_it;
		}
		// write a new line to separate each word from the next
		cout << endl;
	}

	return 0;
}



#include <map>           // 引入映射容器库（map）用于存储每个单词与其出现行数的对应关系
#include <iostream>      // 引入标准输入输出流库
#include <string>        // 引入字符串库
#include <vector>        // 引入动态数组（vector）容器库
#include <set>           // 引入集合容器库（set）用于存储行号

#include "split.h"       // 引入自定义头文件split.h，包含split函数的声明

using std::cin;            // 引入标准输入流
using std::cout;           // 引入标准输出流
using std::endl;           // 引入换行符
using std::getline;        // 引入getline函数，用于逐行读取输入
using std::istream;        // 引入输入流类
using std::string;         // 引入字符串类
using std::vector;         // 引入动态数组类
using std::map;            // 引入映射容器类
using std::set;            // 引入集合容器类

// xref 函数：查找每个单词在输入中出现的行号
map<string, set<int> >
xref(istream& in,               // 输入流（默认为cin）
	vector<string> find_words(const string&) = split) // 使用split函数分割单词（默认）
{
	string line;                 // 用于存储每行的文本
	int line_number = 0;         // 当前行号
	map<string, set<int>> ret;   // 存储单词及其出现的行号，使用map<单词, set<行号>>结构

	// 逐行读取输入
	while (getline(in, line)) {
		++line_number;  // 行号自增

		// 将当前行拆分为单词（使用find_words函数，默认是split）
		vector<string> words = find_words(line);

		// 遍历当前行中的每个单词，将其对应的行号插入到map中
		for (vector<string>::const_iterator it = words.begin(); it != words.end(); ++it)
			ret[*it].insert(line_number);  // 将单词及其行号存入map
	}
	return ret;  // 返回map，包含每个单词及其出现的行号
}

int main()
{
	// 调用xref函数，默认使用split函数进行单词拆分，输入来自cin
	map<string, set<int>> ret = xref(cin);

	// 输出结果：每个单词及其出现的行号
	for (map<string, set<int>>::const_iterator it = ret.begin(); it != ret.end(); ++it) {
		// 输出单词
		cout << it->first << " occurs on line(s): ";

		// 输出该单词出现的所有行号
		set<int>::const_iterator line_it = it->second.begin();
		cout << *line_it;    // 输出第一个行号

		++line_it;
		// 输出其余行号
		while (line_it != it->second.end()) {
			cout << ", " << *line_it;
			++line_it;
		}

		// 输出换行符，以分隔每个单词的输出
		cout << endl;
	}

	return 0;  // 程序结束
}
