ACdream P1121 喵喵的IDE

本文介绍了一道ACdream上的编程题目,涉及一个带有缓存和编辑区的神奇IDE。喵喵需要在IDE中通过三种操作打印出一系列字符串。题目要求找出完成每个字符串打印所需的最少操作数。解决方案可以通过建立字典树来优化,维护每个字母后面串的最小长度,从而求解。作者计划记录集训期间的题目,以便进一步理解和提高。

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

喵喵的IDE

Time Limit: 20000/10000MS (Java/Others) Memory Limit: 512000/256000KB (Java/Others)
Problem Description

喵喵有一个神奇的IDE,这个IDE自带一个cache,还有一个当前编辑区editarea,初始的时候这个 cache 中有一个字符串 cachebegin

喵喵想打按照顺序打N个字符串 x,她可以进行三种操作。

打之前 editarea 为空
1、从cache中拿出一个字符串 B直接赋值给editarea , editarea = B.(如果不拿那么不计入操作数)
2、如果editarea里面有字符,那wuyiqi可以删除掉editarea中最后一个字符。(删光了之后就不能删除啦!)
3、喵喵可以在editarea末尾插入一个任意字符。
如果editarea的字符串恰好与她要打的第i个字符串相同,那么她就完成了这次打印,并且这个字符串自动加入cache(cache中可能出现重复字符串),然后editarea自动清空。那么喵喵就会自动进入下一个字符串的打印阶段。
她想问,对于每次字符串输出,最少需要多少次操作。
1 ≤ N ≤ 105 , 字符串长度总和 ∑(Ai) <106 , cache_begin 长度< 100

Input

第一行一个整数T,代表数据组数。

对于每组数据第一行一个整数 N 代表要打印的字符串个数,还有一个字符串cachebegin

以下N 行每行一个字符串 Ai

A和 cachebegin 都只包含小写字母

Output
对于每组测试数据输出N个数。
Sample Input
1
3 a
a
ab
abc
Sample Output
1
2
2
Hint

一开始cache中为{"a"}
第一次操作直接拿出来{"a"}就好了

现在cache为{"a","a"}
拿出来"a",加入b,两次操作。

现在cache为{"a" , "a" , "ab"}
拿出来"ab",加入c。两次操作

Source
Dshawn & zhanyl
Manager



ACdream上的题目总是恶意卖萌- -,这题一看到最先想到的就是建字典树,看了眼数据分析了一下之后的确也是可以用字典树的,建字典树每一串字母加进去要维护每个字母之后串的最小长度,这样在求一个字母最短时间的时候就是

min(res,q[p].minl+int(strlen(str)-i+1))了,注意每个字母至少在自己的长度之内是可以得到的。


#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<string>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<stack>
#include<cmath>
#define MM(a,t) memset(a,t,sizeof(a))
#define INF 1e9
typedef long long ll;
#define mod 1000000007
const int kind=26;
using namespace std;
struct node {
    int next[kind];
    int minl;
    int gen;
}q[1000002];
int zl,n,root;
char st[1000020];
int gget()
{
  zl++;
  q[zl].gen=0;
  q[zl].minl=1000020;
  memset(q[zl].next,0,sizeof(q[zl].next));
  return zl;
}
void insert(char str[1000020],int root)
{
    int p=root;
    int i=0,index;
    while(str[i])
    {
        index=str[i]-'a';
        if(q[p].next[index]==0)
        {
          q[p].next[index]=gget();
          q[q[p].next[index]].gen=p;
        }
        p=q[p].next[index];
        i++;
    }
    q[p].minl=0;
}
void addup(int ii)
{
    int i,j,p=ii;
     
    while(q[p].gen!=1)
    {
      int tmp=q[p].minl+1;
      p=q[p].gen;
      q[p].minl=min(q[p].minl,tmp);
    }
}
int query(char str[1000020],int root)
{
    int res=strlen(str),p=root;
    int i,j,index;
    bool ff;
     
    i=0; ff=false;
    while(str[i])
    {
      index=str[i]-'a';
      if(q[p].next[index]==0)
      {
        res=min(res,q[p].minl+int(strlen(str)-i+1));
        ff=true;
        break; 
      }
      p=q[p].next[index];
      i++; 
      res=min(res,q[p].minl+int(strlen(str)-i+1));
    }
     
    return res;
}
int main()
{
    int i,j,T;
     
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        cin>>st;
        zl=0; root=gget();
        insert(st,root);
        for(i=1;i<=n;i++)
        {
            cin>>st;
            addup(zl);
            printf("%d\n",query(st,root));
            if(i!=n) insert(st,root);
        }
         
    }
     
     
    return 0;
}


但是做完后发现我的需要跑4000MS左右啊,排在首页的都是2000MS之内的,甚至还有1000MS之内的,有人能告诉我怎么做吗?


明天开始想记录一些集训时候的题目了,毕竟集训时那么多题目没搞懂就来刷ACdream总是不地道。。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值