nowcoder15975 小C的记事本

本文探讨了一种高效的文本编辑器操作模拟方法,通过构建树状结构来维护字符串的修改历史,支持撤销、插入和删除操作。文章提供了两种实现方案,一种采用持久化栈,另一种则采取直接暴力撤销策略,旨在降低复杂度并提高效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

链接

点击跳转

做法一

可持久化栈,其实就是一棵树。

要维护每个结点的深度、每个结点的父节点、当前的根节点,之前的根节点。

还要维护当前字符串,以及当前字符串长度。写了半天才调过。

写完这个题我开始怀疑:这真的是两星的题???

于是想了半天我突然开窍了,这题直接暴力好像就行了嘛

做法二

记录每次操作是插入了什么字符串,或者删除了什么字符串。

因为每个字符最多插入一次,删除一次,所以时间复杂度是线性的。

撤销的时候,直接暴力撤销就行了。

代码一

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define iinf 0x3f3f3f3f
#define linf (1ll<<60)
#define eps 1e-8
#define maxn 1000010
#define maxe 1000010
#define cl(x) memset(x,0,sizeof(x))
#define rep(i,a,b) for(i=a;i<=b;i++)
#define drep(i,a,b) for(i=a;i>=b;i--)
#define em(x) emplace(x)
#define emb(x) emplace_back(x)
#define emf(x) emplace_front(x)
#define fi first
#define se second
#define de(x) cerr<<#x<<" = "<<x<<endl
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
ll read(ll x=0)
{
    ll c, f(1);
    for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
    for(;isdigit(c);c=getchar())x=x*10+c-0x30;
    return f*x;
}
char nd[maxn], s[maxn], now[maxn];
ll top[maxn], fa[maxn], dep[maxn];
int main()
{
    ll i, top_tot, q, nd_tot, len;
    while(~scanf("%lld",&q))
    {
        ll i, j;
        top_tot = nd_tot = len = 0;
        rep(i,1,q)
        {
            ll type=read();
            if(type==1)
            {
                scanf("%s", s);
                ll n = strlen(s);
                ll pre = top[top_tot];
                rep(j,0,n-1)
                {
                    fa[nd_tot+1] = pre;
                    nd_tot ++;
                    nd[nd_tot] = s[j];
                    now[++len] = s[j];
                    dep[nd_tot] = dep[pre] +1;
                    pre = nd_tot;
                }
                top_tot++;
                top[top_tot] = nd_tot;
                rep(j,0,n-1)s[j]=0;
            }
            else if(type==2)
            {
                top_tot++, top[top_tot]=top[top_tot-1];
                ll k=read();
                while(k--)top[top_tot] = fa[top[top_tot]], len--;
            }
            else if(type==3)
            {
                ll k=read();
                putchar(now[k]); putchar(10);
            }
            else
            {
                top_tot --;
                if(dep[top[top_tot]] < len)len = dep[top[top_tot]];
                else
                {
                    ll t=dep[top[top_tot]];
                    for(j=top[top_tot];dep[j]>len;j=fa[j])now[t--]=nd[j];
                    len = dep[top[top_tot]];
                }
            }
        }
    }
    return 0;
}

代码二

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define iinf 0x3f3f3f3f
#define linf (1ll<<60)
#define eps 1e-8
#define maxn 2000010
#define cl(x) memset(x,0,sizeof(x))
#define rep(i,a,b) for(i=a;i<=b;i++)
#define drep(i,a,b) for(i=a;i>=b;i--)
#define em(x) emplace(x)
#define emb(x) emplace_back(x)
#define emf(x) emplace_front(x)
#define fi first
#define se second
#define de(x) cerr<<#x<<" = "<<x<<endl
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
ll read(ll x=0)
{
    ll c, f(1);
    for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
    for(;isdigit(c);c=getchar())x=x*10+c-0x30;
    return f*x;
}
ll pos[maxn], len[maxn], slen, tp[maxn];
char S[maxn], nows[maxn], s[maxn];
int main()
{
    ll i, now, q;
    len[0]=1;
    while(~scanf("%lld",&q))
    {
        ll i, j;
        now = 0, slen = 0;
        rep(i,1,q)
        {
            ll type=read();
            if(type==1)
            {
                scanf("%s",s);
                ll n = strlen(s);
                now++;
                tp[now] = 1;
                pos[now] = pos[now-1]+len[now-1];
                len[now] = 0;
                rep(j,0,n-1)
                {
                    S[pos[now]+(len[now]++)] = s[j];
                    nows[++slen]=s[j];
                    s[j]=0;
                }
            }
            else if(type==2)
            {
                ll k=read();
                now++;
                tp[now] = 2;
                pos[now] = pos[now-1]+len[now-1];
                len[now] = 0;
                rep(j,slen-k+1,slen)
                    S[pos[now]+(len[now]++)] = nows[j];
                slen -= k;
            }
            else if(type==3)
            {
                ll k=read();
                putchar(nows[k]); putchar(10);
            }
            else
            {
                if(tp[now]==1)
                {
                    rep(j,1,len[now])slen--;
                }
                else
                {
                    rep(j,0,len[now]-1)nows[++slen]=S[pos[now]+j];
                }
                now--;
            }
            // de(S+1);
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值