D

一道看上去就很链表的模拟题。
vim 使用者对此题有些莫名的感慨……

在 Normal Mode 下

  • 按下 i :进入 Insert Mode 。
  • 按下 f :紧接着一个小写字母 char,若当前光标后(右)方有至少一个 char ,将光标移动到其所在位置,否则不移动。
  • 按下 x :删除当前光标所在位的字符,后面的字符均会前移一格。
  • 按下 h :将光标向左(前)移动一格,若无法移动就不移动。
  • 按下 l :将光标向右(后)移动一格,若无法移动就不移动。
  • 若按下了其他字符:无任何效果。

在 Insert Mode 下

  • 按下非 e 小写字母 char :在光标当前位置前插入这个字母 char。
  • 按下 e :退出 Insert Mode(进入 Normal Mode)。

如果使用链表,绝大部分操作都是 的,唯一看起来具有威胁的就是按下 f 的操作,单次操作极限可以达到 ,但均摊复杂度是正确的。
因为 f 操作单调右移,而题中唯一的左移操作每次只能移动一个单位,也就是说,每次 f 消耗的势能,都只能通过按下 h 来补充,对总体复杂度无影响。

#include <cstdio>
#include <list>
#include <cstring>
#include <algorithm>
#include <ctype.h>
using namespace std;
const int bufSize = 1e6;
inline char nc()
{
    #ifdef DEBUG
    return getchar();
    #endif
    static char buf[bufSize], *p1 = buf, *p2 = buf;
    return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, bufSize, stdin), p1 == p2) ? EOF : *p1++;
}
inline void read(char *s)
{
    static char c;
    for (; !isalpha(c); c = nc());
    for (; isalpha(c); c = nc()) *s++ = c;
    *s = '\0';
}
const int maxn = 2e5 + 100;
char s[maxn],t[maxn];
list<char> now;
int len,num;
int main()
{
    read(s + 1),read(t + 1);
    len = strlen(s + 1),num = strlen(t + 1);
    for(int i = 1;i<=len;++i) now.push_back(s[i]);
    int mode = 0;//0 for normal mode,1 for insert mode
    list<char>::iterator cur = now.begin();
    for(int i = 1;i<=num;++i)
    {
        char opt = t[i];
        if(mode == 0)
        {
            if(opt == 'i') mode = 1;
            else if(opt == 'f') 
            {
                char tar = t[++i];
                list<char>::iterator it = cur;
                ++it;
                while(it != now.end() && it != now.end())
                {
                    if(*it == tar) 
                    {
                        cur = it;
                        break;
                    }
                    ++it;
                }
            }
            else if(opt == 'x') cur = now.erase(cur);
            else if(opt == 'h') 
            {
                if(cur == now.begin()) continue;
                --cur;
            }
            else if(opt == 'l')
            {
                if(cur == now.end()) continue;
                ++cur;
            }
        }
        else
        {
            if(opt == 'e') mode = 0;
            else now.insert(cur,opt);
        }
    }
    for(list<char>::iterator it = now.begin();it!=now.end();++it) putchar(*it);
    return 0;
}