ACdream P1121 喵喵的IDE

喵喵的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總是不地道。。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章