记事本问题

A : 记事本

题目描述

记事本是 Windows 平台下一款经典的文本编辑器,其存储文件的扩展名为 .txt,文件属性没有任何格式标签或者风格,所以相当适合在 DOS 环境中编辑。

在本题中,可能会用到的按键如下图所示:

光标移动

光标表示当前要进行输入等操作的位置,在本题中,我们假设所有字符都是等宽的。

光标的位置可以用行列坐标来描述,光标所在的行和列均从 1 开始,例如:

以下操作可以进行光标的移动,使用 MOVE <comd> 输入相关的操作,其中 <comd> 表示指令,可以使用以下字符串代替:

  • Home:把光标移动到当前行的开头。
  • End:把光标移动到当前行的末尾。
  • Up:光标移动到上一行的相同列。
    • 若当前为第一行,则不进行任何操作。
    • 若上一行的列数小于当前光标的列数,则将光标移动到上一行的末尾。
  • Down:光标移动到下一行的相同列。
    • 若当前为最后一行,则不进行任何操作。
    • 若下一行的列数小于当前光标的列数,则将光标移动到下一行的末尾。
  • Left:光标左移一位。
    • 若当前光标位于记事本开始,则不进行任何操作。
    • 若当前光标处于某一行的开头,则将光标移动到上一行的末尾。
  • Right:光标右移一位。
    • 若当前光标位于记事本末尾,则不进行任何操作。
    • 若当前光标处于某一行的末尾,则将光标移动到下一行的开头。

输入

以下操作可以在光标后进行输入,使用 INSERT <comd> 输入相关的操作,其中 <comd> 表示指令,可以使用以下字符串代替:

  • Char <char>:输入一个字符,其中 <char> 是输入的字符。

    • <char> 可能是一下字符中的任意一个:

    注:下列字符中不包含空格与换行符

    `1234567890-=~!@#$%^&*()_+qwertyuiop[]\QWERTYUIOP{}|asdfghjkl;'ASDFGHJKL:"zxcvbnm,./ZXCVBNM<>?
    
    • 例如:INSERT Char a 表示在当前光标后插入 a 字符。
  • Enter:输入换行符,并进行换行。

  • Space:输入空格。

  • Paste:在当前光标后,插入粘贴板中的内容,若粘贴板中无内容,则忽略当前操作。

删除

以下操作可以删除记事本中的内容,使用 REMOVE <comd> 输入相关的操作,其中 <comd> 表示指令,可以使用以下字符串代替:

  • Del:删除当前光标位置之后的一个字符。
    • 若该字符为换行符,则当前行与下一行合并为一行。
    • 若当前光标在文件末尾,则忽略当前操作。
  • Backspace:删除当前光标位置之前的一个字符。
    • 若该字符为换行符,则当前行与上一行合并为一行。
    • 若当前光标在文件开头,则忽略当前操作。

粘滞功能(分数占比 24 分)

输入 SHIFT 指令,可以启动或关闭粘滞功能。

  • 开始时粘滞功能默认为关闭状态,之后每次点击:

    • 若当前为启动状态,则关闭;
    • 若当前为关闭状态,则启动。
  • 粘滞功能启动时,记录当前的光标位置为 记录点

  • 粘滞功能关闭时,若此时的光标位置与 记录点 的位置不同,则进入选中状态

  • 粘滞功能启动后,直到功能关闭前,不会对记事本进行除光标移动外的任何操作

当进入选中状态后,通过记录点与当前光标,可以唯一的确定一段内容,现令记录点与光标之间的所有字符(包括换行符)为 选中字段

例如,记录点位于第 1 行第 2 列,光标位于第 2 行第 4 列时,选中字段如下图所示:

当前 处于选中状态 时,对于不同的情况,需要按照序号依次执行以下操作:

  • 若进行光标移动

    1. 退出选中状态
    2. 尝试进行光标的移动(无论光标最终是否移动,都会退出选中状态)。
  • 若进行输入

    1. 将选中内容替换为输入内容;
    2. 退出选中状态
  • 若进行删除

    1. 删除当前选中内容;
    2. 退出选中状态
  • 若再次启动粘滞功能退出选中状态,但保留上一次选中字段的 记录点 作为当前记录点

  • 若进行查找,字数统计,复制,打印操作,则在操作后仍然保持选中状态

查找

输入 FIND <word> 指令,进行字符串查找,其中 <word> 为输入的要查找的字符串,该字符串中不包含空格与换行符。

执行该指令时,要根据当前是否处于选中状态做不同的处理:

  • 若当前处于选中状态:查找输入字符串在选中字段中的出现次数并输出。
  • 否则:查找输入字符串在当前记事本中的出现次数并输出。

例如:当前没有选中的内容,且记事本中的内容为 ababa,若执行 FIND aba,则应当输出 2,分别在第 1 列与第 3 列出现过。

字数统计

输入 COUNT 指令,进行字数统计。

执行该指令时,要根据当前是否处于选中状态做不同的处理:

  • 若当前处于选中状态:输出当前选中字段中的可见字符(不包括空格与换行符)的数量。
  • 否则:输出当前文档中可见字符(不包括空格与换行符)的数量。

复制

输入 COPY 指令,进行复制操作。

执行该指令时,要根据当前是否处于选中状态做不同的处理:

  • 若当前处于选中状态:复制选中字段到粘贴板;
  • 否则,
    • 若当前行不为空:复制当前行的内容(不包括换行符)到粘贴板;
    • 否则:忽略当前操作。

打印

输入 PRINT 指令,输出当前的记事本中的全部内容,并在之后输出一个换行符。

输入格式

输入包含 n+1 行。
第一行包含一个整数 n,表示接下来指令的数量。
接下来 n 行,每行一条指令,格式形如题目描述中的叙述。

输出格式

对于需要输出的指令,进行相应的输出。
若为 FIND 与 COUNT 操作,输出一行表示相应的数字。
若为 PRINT 操作,则输出若干行,表示记事本的当前内容,并在之后输出一个换行。

请注意:所有的输出不要有多余的空格。

测试样例

样例输入

20
INSERT Char #
INSERT Enter
INSERT Char C
INSERT Enter
INSERT Space
INSERT Char _
INSERT Char _
PRINT
INSERT Char >
INSERT Enter
INSERT Char h
INSERT Char h
INSERT Char h
INSERT Enter
PRINT
COUNT
FIND __
REMOVE Del
REMOVE Backspace
PRINT

样例输出

#
C
 __
#
C
 __>
hhh

8
1
#
C
 __>
hhh

数据规模

对于 100% 的测试数据,1≤n≤5000。

不同测试点所包含的功能不同,其具体情况如下表所示。

思路: 我的思路是使用vector<string>作为数据结构,string存放每句话,而vector存放话。那么接下来我们将光标抽象为一个x,y的点,利用光标即可索引该位置的数据。选中状态我们设置为_sel,和是否选中sel2,复制内容我们使用vector<string>,记录点使用p2。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
pair<int, int> p;
vector<string> book;
vector<string> cpy;
bool _sel;
bool sel2;
pair<int, int>p2;//记录点
int n;
int subString(string str, string sub)
{
	int count = 0, i, j;
	for (i = 0; i < str.length(); i++) {
		for (j = 0; j < sub.length(); j++) {
			if (str[i + j] != sub[j]) {
				break; // 出现了不同字符就退出循环
			}
		}
		if (j == sub.length()) {
			count++; // 退出循环后若j的值等于子串的长度,则存在子串
		}
	}
	return count;
}
void Home() {
	 p.second = 0;//初始值设置为0.因为数组的初值从0开始。
}
void End() {
	if(!book.empty()){
		if (p.first != book.size() - 1)
			p.second = book[p.first].size() - 1;//最后一行没有“、n”
		else
			p.second = book[p.first].size();
	}
}
void Up() {
	if (!book.empty()) {
		if (p.first != 0){
			if (p.second >= book[p.first - 1].size()-1) {//当前光标行大于上面的光标行,到末尾
				p.second = book[p.first - 1].size() - 1;
				p.first--;
			}
			else {
				p.first--;
			}
		}
	}
}
void Down() {
	if (!book.empty()) {
		if (p.first != book.size() - 1){
			if (p.first!=book.size()-2) {
				if (p.second >= (book[p.first + 1].size() - 1)) {
					p.second = book[p.first + 1].size() - 1;
					p.first++;
				}
				else {
					p.first++;
				}
			}
			else {
				if (p.second >= book[p.first + 1].size()) {
					p.second = book[p.first + 1].size();
					p.first++;
				}
				else {
					p.first++;
				}
			}
		}
	}
};
void Left() {
	if (!book.empty()) {
		if (p.second == 0) {//开头
			if (p.first != 0){
				p.first--;
				p.second = book[p.first].size() - 1;
			}
		}
		else {
			p.second--;
		}
	}
}
void Right() {
	if (!book.empty()) {
		if (p.first == book.size() - 1) {//zuihou
			if (p.second < (book[p.first].size()))p.second++;
		}
		else {
				if (p.second == book[p.first].size() - 1) {
					p.first++;
					p.second = 0;
				}
				else p.second++;
		}
	}
}
void Char(char s) {
	if (!book.empty()) {
		book[p.first].insert(book[p.first].begin() + p.second, s);
	}
	else {
		string tmp;
		tmp.push_back(s);
		book.push_back(tmp);
	}
	p.second++;
}
void Enter() {
	if (!book.empty()) {
		if (p.first != book.size() - 1) {
			//if (p.second != book[p.first].size() - 1) {
				book[p.first].insert(book[p.first].begin() + p.second, '\n');
				int x = book[p.first].size() - p.second -1;
				string a;
				for (int i = 1; i <= x; i++) {
					a.insert(a.begin(), book[p.first].back());
					book[p.first].pop_back();
				}
				book.insert(book.begin() + p.first+1, a);
				p.first++;p.second = 0;
			//}
		//	else if(p.second==book[p.first].size()-1){
			//	book.insert(book.begin() + p.first+1, "\n");
			//	p.first++; p.second = 0;
			//}
		}
		else  {
			//if (p.second != book[p.first].size()) {
				book[p.first].insert(book[p.first].begin() + p.second, '\n');
				int x = book[p.first].size() - p.second -1;
				string a;
				for (int i = 1; i <= x; i++) {
					a.insert(a.begin(),book[p.first].back());
					book[p.first].pop_back();
				}
				book.insert(book.begin() + p.first+1, a);
				p.first++; p.second = 0;
			//}
			//else {
				//string a ;
			//	book[p.first] += "\n";
			//	book.push_back(a);
			//	p.first++; p.second = 0;
			//}
		}
	}
	else {
		book.push_back("\n");
		string a;
		book.push_back(a);
		p.first++; p.second = 0;
	}
	huiche++;
}
void Space() {
	if (!book.empty()) {
		book[p.first].insert(book[p.first].begin() + p.second, ' ');
	}
	else { string a = " "; book.push_back(a); }
	p.second++;
	kongge++;
}
void Paste() {
	if (cpy.size() == 0);
	else if (cpy.size() == 1) {
		//if (*(cpy[0].end() - 1) != '\n') {
			book[p.first].insert(book[p.first].begin() + p.second, cpy[0].begin(), cpy[0].end());
			p.second += (cpy[0].size());
		/*}
		else {
			string tmp;
			for (int j = p.second; j < book[p.first].size(); j++) {
				tmp.push_back(book[p.first][j]);
			}
			book[p.first].erase(book[p.first].begin() + p.second, book[p.first].end() - 1);
			book[p.first].insert(book[p.first].end() - 1, cpy[0].begin(), cpy[0].end());
			book.insert(book.begin() + p.first, tmp);
			p.first++; p.second = 0;

		}*/
	}
	else {//duohang
		string tmp;
		for (int j = p.second; j < book[p.first].size(); j++) {
			tmp.push_back(book[p.first][j]);
		}
		book[p.first].erase(book[p.first].begin() + p.second, book[p.first].end());
		book[p.first] += cpy[0];
		//book.insert(book.begin() + p.first, tmp);
		//tmp.clear();
		book.insert(book.begin() + p.first+1, cpy.begin() + 1, cpy.end());
		book[p.first + cpy.size() - 1] += tmp;
		tmp.clear();
		p.first += (cpy.size()-1);
		p.second = (cpy[cpy.size() - 1].size());
	}
}
void Del() {//debug到这里,光标位置
	if (!book.empty()) {
		if (p.first == book.size() - 1 && p.second == book[p.first].size()) {
			return;
		}

		else if (p.first != book.size() - 1 && p.second < book[p.first].size() - 1) {
			book[p.first].erase(book[p.first].begin() + p.second); 
		}
		else if (p.first == book.size() - 1 && p.second < book[p.first].size()) {
			book[p.first].erase(book[p.first].begin() + p.second); 
		}
		else
		{
			book[p.first].erase(book[p.first].end() - 1);//"\n"
			book[p.first] += book[p.first + 1];
			book.erase(book.begin() + p.first + 1);
		}
	}
}
void Backspace() {//注意光标位置
	if (!book.empty()) {
		if (p.first == 0 && p.second == 0) {
			return;
		}
		else {
			if (p.second > 0) {
				book[p.first].erase(book[p.first].begin() + p.second - 1);//true
				p.second--;
			}
			else {
				book[p.first - 1].erase(book[p.first - 1].end() - 1);//true
				p.second = book[p.first - 1].size();
				book[p.first - 1] += book[p.first];
				book.erase(book.begin() + p.first);
				p.first--;
			}
		}
	}
}
void sel() {
	if (_sel) _sel = 0;
	else _sel = 1;
	if (_sel) {//如启动,记录点
		if (!sel2) {
			p2.first = p.first, p2.second = p.second;
		}
		else { sel2 = 0; }
	}
	else {//如果关闭
		if (p2.first != p.first || p2.second != p.second) {
			sel2 = 1;//xuanzhong
		}
	}
}
void COUNT();
void COPY() {
	
	if (sel2) {
		cpy.clear();
		if (p2.first < p.first) {
			string tmp;
			for (int j = p2.second; j < book[p2.first].size(); j++) {
				tmp.push_back(book[p2.first][j]);
			}
			cpy.push_back(tmp);
			tmp.clear();
			for (int i = p2.first + 1; i < p.first; i++) {
				cpy.push_back(book[i]);
			}
			for (int j = 0; j < p.second; j++) {
				tmp.push_back(book[p.first][j]);
			}
			cpy.push_back(tmp);
			tmp.clear();
		}
		else if (p2.first == p.first) {
			string tmp;
			if (p2.second > p.second) {
				for (int j = p.second; j < p2.second; j++) {
					tmp.push_back(book[p2.first][j]);
				}
				cpy.push_back(tmp);
				tmp.clear();
			}
			else if (p2.second < p.second) {
				for (int j = p2.second; j < p.second; j++) {
					tmp.push_back(book[p.first][j]);
				}
				cpy.push_back(tmp);
				tmp.clear();
			}
		}
		else {
			string tmp;
			for (int j = p.second; j < book[p.first].size(); j++) {
				tmp.push_back(book[p.first][j]);
			}
			cpy.push_back(tmp);
			tmp.clear();
			for (int i = p.first + 1; i < p2.first; i++) {
				cpy.push_back(book[i]);
			}
			for (int j = 0; j < p2.second; j++) {
				tmp.push_back(book[p2.first][j]);
			}
			cpy.push_back(tmp);
			tmp.clear();
		}
	}
	else {
			if (p.first < book.size() - 1 && book[p.first].size()>1) {
				cpy.clear();
				cpy.push_back(book[p.first]);
				cpy[0].pop_back();
			}
			else if (p.first == book.size() - 1 && book[p.first].size() > 0) {
				cpy.clear();
				cpy.push_back(book[p.first]);
			}
	}
}
void PRINT() {
	for (int i = 0; i < book.size(); i++) {
		cout << book[i];
	}
	cout << "\n";
}
void del() {
	if (p.first < p2.first) {
			book[p.first].erase(book[p.first].begin() + p.second, book[p.first].end());
			book.erase(book.begin() + p.first+1, book.begin() + p2.first);
			book[p.first+1].erase(book[p.first+1].begin(), book[p.first+1].begin() + p2.second);
			book[p.first] += book[p.first + 1];
			book.erase(book.begin()+p.first+1);
	}
	else if(p2.first==p.first){
	 if (p.second < p2.second) {
		 book[p.first].erase(book[p.first].begin() + p.second, book[p.first].begin() + p2.second);
		}
		else {
		 book[p.first].erase(book[p.first].begin() + p2.second, book[p.first].begin() + p.second);
		 p.second = p2.second;
		}
	}
	else {
		book[p2.first].erase(book[p2.first].begin() + p2.second, book[p2.first].end());
		book.erase(book.begin() + p2.first + 1, book.begin() + p.first);
		book[p2.first+1].erase(book[p2.first+1].begin(), book[p2.first+1].begin() + p.second);
		book[p2.first] += book[p2.first + 1];
		book.erase(book.begin() + p2.first+1);
		p.first = p2.first; p.second = p2.second;
	}
}
void FIND(string word);
int main() {
	//freopen("cao.in", "r", stdin);
	//freopen("22my.out", "w", stdout);
	cin >> n;
	for (int i = 0; i < n; i++)
	{
		string a;
		cin >> a;
		if (a == "INSERT") {
			string b;
			cin >> b;
			if (b == "Char") {
				string c;
				cin >> c;
				if (!_sel && !sel2) {
					Char(c[0]);
				}
				else if (!_sel&&sel2) {
					del();
					Char(c[0]);
					sel2 = 0;
				}
			}
			else if (b == "Enter") {
				if (!_sel && !sel2)
					Enter();
				else if (!_sel&&sel2) {
					del();
					Enter();
					sel2 = 0;
				}
			}
			else if (b == "Space") {
				if (!_sel && !sel2)
					Space();
				else if (!_sel&&sel2) {
					del();
					Space();
					sel2 = 0;
				}
			}
			else if (b == "Paste") {
				if (!_sel && !sel2)
					Paste();
				else if (!_sel&&sel2) {
					del();
					Paste();
					sel2 = 0;
				}
			}
		}
		else if (a == "PRINT") {
			if (!_sel) {
				PRINT();
			}
		}
		else if (a == "COUNT") {
			if (!_sel) {
				COUNT();
			}
		}
		else if (a == "FIND") {
			string word;
			cin >> word;
			if (!_sel) {
				FIND(word);
			}
		}
		else if (a == "COPY") {
			if (!_sel) {
				COPY();
			}
		}
		else if (a == "SHIFT") {
			sel();
		}
		else if (a == "REMOVE") {

			string b;
			cin >> b;
			if (b == "Del") {
				if (!_sel && !sel2) {
					Del();
				}
				else if(!_sel&&sel2) {
					del();
					sel2 = 0;
				}
			}
			else if (b == "Backspace") {
				if (!_sel&&!sel2) {
					Backspace();
				}
				else if (!_sel&&sel2) {
					del();
					sel2 = 0;
				}
			}
		}
		else if (a == "MOVE") {
			string b;
			cin >> b;
			if (!sel2) {
				if (b == "Home") {
					Home();
				}
				else if (b == "End") {
					End();
				}
				else if (b == "Up") {
					Up();
				}
				else if (b == "Down") {
					Down();
				}
				else if (b == "Right") {
					Right();
				}
				else if (b == "Left") {
					Left();
				}
			}
			else {
				if (b == "Home") {
					Home();
				}
				else if (b == "End") {
					End();
				}
				else if (b == "Up") {
					Up();
				}
				else if (b == "Down") {
					Down();
				}
				else if (b == "Right") {
					Right();
				}
				else if (b == "Left") {
					Left();
				}
				sel2 = 0;
			}
		}
	}
	return 0;
}
void FIND(string word) {
	int count = 0;
	if (sel2) {
		if (p2.first < p.first) {
			string tmp;
			tmp.insert(tmp.begin(), book[p2.first].begin()+p2.second, book[p2.first].end());
			count += (subString(tmp, word));
			tmp.clear();
			for (int i = p2.first + 1; i < p.first; i++) {
					count += (subString(book[i], word));
			}
			tmp.insert(tmp.begin(), book[p.first].begin(), book[p.first].begin()+p.second);
			count += (subString(tmp, word));
			
		}
		else if (p2.first == p.first) {
			if (p2.second < p.second) {
				string tmp;
				for (int j = p2.second; j < p.second; j++) {
					tmp.push_back(book[p2.first][j]);
				}
				count += (subString(tmp, word));
			}
			else {
				string tmp;
				for (int j = p.second; j< p2.second; j++) {
					tmp.push_back(book[p.first][j]);
				}
				count += (subString(tmp, word));
			}
		}
		else {
			string tmp;
			tmp.insert(tmp.begin(), book[p.first].begin() + p.second, book[p.first].end());
			count += (subString(tmp, word));
			tmp.clear();
			for (int i = p.first + 1; i < p2.first; i++) {
				count += (subString(book[i], word));
			}
			tmp.insert(tmp.begin(), book[p2.first].begin(), book[p2.first].begin() + p2.second);
			count += (subString(tmp, word));
		}
	}
	else {
		for (int i = 0; i < book.size(); i++) {
			count+=(subString(book[i], word));
		}
	}
	cout << count << endl;
}
bool look(char a) {
	if (a == '\n') return false;
	if (a == ' ')return false;
	return true;
}
void COUNT() {
	int count = 0;
	if (sel2) {
		if (p2.first < p.first) {
			for (int j = p2.second; j < book[p2.first].size(); j++) {
				if (look(book[p2.first][j])) count++;
			}
			for (int i = p2.first + 1; i < p.first; i++) {
				for (int j = 0; j < book[i].size(); j++) {
					if (look(book[i][j])) count++;
				}
			}
			for (int j = 0; j < p.second; j++) {//gengai
				if (look(book[p.first][j])) count++;
			}
		}
		else if (p2.first == p.first) {
			if (p2.second < p.second) {
				for (int j = p2.second; j < p.second; j++) {
					if (look(book[p2.first][j])) count++;
				}
			}
			else {
				for (int j = p.second; j < p2.second; j++) {
					if (look(book[p2.first][j])) count++;
				}
			}
		}
		else {
			for (int j = p.second; j < book[p.first].size(); j++) {
				if (look(book[p.first][j])) count++;
			}
			for (int i = p.first + 1; i < p2.first; i++) {
				for (int j = 0; j < book[i].size(); j++) {
					if (look(book[i][j])) count++;
				}
			}
			for (int j = 0; j < p2.second; j++) {
				if (look(book[p2.first][j])) count++;
			}
		}
	}
	else {
		for (int i = 0; i < book.size(); i++) {
			for (int j = 0; j < book[i].size(); j++) {
				if (look(book[i][j])) count++;
			}
		}
		//count -= (kongge + huiche);
	}
	cout << count << endl; 
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值