1.题目描述:点击打开链接
2.解题思路:本题要求模拟一个文本编辑器。功能就是题目中描述的那样。为了方便支持插入,删除,替换操作,可以直接使用string来模拟。不过这种题目一般重难点在于对细节的把握。稍微考虑不周就会陷入WARush中。这道题我上来就被这几处细节给坑到了:
(1)新输入的字符,如果在caret右侧没有字符时候,可以看做是insert,而不是忽略它。
(2)对于已经被忽略的字符,仍然会影响mode的属性,因此不要发现不能读入时候直接就continue了。
(3)如果当前clipboard中没有字符串,在粘贴操作中应该直接返回,如果没有特判empty会导致RE。(本题的clipboard可以用一个栈模拟)
以上三条就是我疏忽的细节。在做模拟题时候,可以把注意事项逐条列出,然后一条一条去测试看逻辑是否正确,这样可以防止漏掉某些条件。
3.代码:
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<cassert>
#include<string>
#include<sstream>
#include<set>
#include<bitset>
#include<vector>
#include<stack>
#include<map>
#include<queue>
#include<deque>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<cctype>
#include<complex>
#include<functional>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
#define me(s) memset(s,0,sizeof(s))
#define rep(i,n) for(int i=0;i<(n);i++)
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef pair <int, string> P;
const int N = 10000 + 10;
char text[N];
string ans;
stack<string>clipboard;
int mode, status;
int M; //the limitation
int cur, pos1;
void init()
{
cur = 1;//cur means caret
mode = 0; //0 means insert; 1 means overwrite
status = 0; //0 means NOTHING,1 means START
ans.clear();
ans += '#';
while (!clipboard.empty())
clipboard.pop();
}
void move(int cmd)
{
int len = ans.length();
if (!cmd)
{
if (cur == 1)return;
cur--;
}
else
{
if (cur == len)return;
cur++;
}
}
void del(int cmd)
{
int len = ans.length();
if (cmd&&status == 1)
{
status ^= 1;
int st = min(pos1, cur);
int len = abs(pos1 - cur);
ans.erase(st, len);
cur = st;
return;
}
else if (!cmd)
{
if (cur == 1)return;
ans.erase(cur - 1, 1); cur--;
}
else
{
if (cur == len)return;
ans.erase(cur, 1);
}
}
void copy()
{
if (!status)pos1 = cur, status ^= 1;
else
{
status ^= 1;
int len = abs(pos1 - cur);
int st = min(pos1, cur);
string tmp = ans.substr(st, len);
clipboard.push(tmp);
}
}
void paste()
{
if (clipboard.empty())return;
if (!mode)
{
int len = ans.length(), L1 = clipboard.top().length();
if (len + L1 > M + 1)return;
ans.insert(cur, clipboard.top());
cur += L1;
}
else
{
int L1 = clipboard.top().length();
if (cur + L1 > M + 1)return;
ans.replace(cur, L1, clipboard.top());
cur += L1;
}
}
int main()
{
int T;
scanf("%d", &T);
while (T--)
{
scanf("%d%s", &M, text);
init();
int len = strlen(text);
for (int i = 0; i<len; i++)
{
if (text[i] == 'L') { move(0); continue; }
if (text[i] == 'R') { move(1); continue; }
if (text[i] == 'S') { mode ^= 1; if (status)status = 0; continue; }
if (text[i] == 'D') { del(1); continue; }
if (text[i] == 'B') { del(0); if (status)status = 0; continue; }
if (text[i] == 'C') { copy(); continue; }
if (text[i] == 'V') { paste(); if (status)status = 0; continue; }
if (!mode)
{
if (ans.length() <= M)
{
ans.insert(cur, 1, text[i]);
cur++;
}
}
else
{
if (cur <= M)
{
ans.replace(cur, 1, 1, text[i]);
cur++;
}
}
if (text[i] != 'L'&&text[i] != 'R'&&text[i] != 'D'&&status == 1)
status = 0;
}
if (ans.length() == 1)puts("NOTHING");
else cout << ans.substr(1) << endl;
//printf("current position: %d\n", cur);
}
}