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 列时,选中字段如下图所示:
当前 处于选中状态 时,对于不同的情况,需要按照序号依次执行以下操作:
-
若进行光标移动:
- 退出选中状态;
- 尝试进行光标的移动(无论光标最终是否移动,都会退出选中状态)。
-
若进行输入:
- 将选中内容替换为输入内容;
- 退出选中状态。
-
若进行删除:
- 删除当前选中内容;
- 退出选中状态。
-
若再次启动粘滞功能:退出选中状态,但保留上一次选中字段的 记录点 作为当前记录点。
-
若进行查找,字数统计,复制,打印操作,则在操作后仍然保持选中状态。
查找
输入 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;
}