喵喵的IDE
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
Ai 和 cachebegin 都只包含小寫字母
Output
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
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;
}
明天開始想記錄一些集訓時候的題目了,畢竟集訓時那麼多題目沒搞懂就來刷ACdream總是不地道。。。。