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