【Trie+vector】BZOJ4896(Thu Summer Camp2016)[补退选]题解

来源:互联网 发布:中文域名转码 源码 编辑:程序博客网 时间:2024/06/06 13:21

题目概述

有n个事件,分为三类:
1.插入字符串S。
2.删除字符串S。
3.求最小的pos,使第pos个事件结束后,以S为前缀的字符串个数>v。

解题报告

这种插入和删除字符串还要问前缀(而且还有强制在线)的题目我们不难想到用Trie解决。只是这个询问比较奇怪,但用STL乱搞就很容易了(滑稽:P)。

为每一个Trie节点记录一个vector,表示w分别为1,2,3,…时的最早事件编号,那么每次询问v时输出w为v+1时的最早事件编号就行了(因为每次w只会+1,所以v+1的最早事件编号绝对比>v+1的最早事件编号小),非常暴力……

但是这样vector会不会炸空间呢?不会。思考一下我们会发现只有插入的时候vector才会进入新的元素,删除是不会的(因为删除让w减小了)。而每次插入最多遍历到len(len是字符串长度)个节点,所以所有节点vector元素的总数为n*len,是可以承受的。

ps:这道题题目描述自相矛盾,没有说清楚到底是26个小写字母还是10个小写字母,不过好像用指针动态处理就没什么事了(但我还是开了10=_=)

示例程序

#include<cstdio>#include<vector>using namespace std;typedef long long LL;const int maxn=100000,maxl=60,maxt=maxn*maxl,maxi=10;int te,ans;char s[maxl+5];struct Trie{    struct node    {        int w,id;node* son[maxi];vector<int> que;        node(int a,int b) {w=a;id=b;for (int i=0;i<maxi;i++) son[i]=0;}    };    typedef node* P_node;    int si;P_node ro;    Trie() {si=0;ro=new node(0,0);}    int ID(char ch) {return ch-'a';}    void Insert(char *s,int te)    {        P_node pos=ro;        for (int i=1;s[i];i++)        {            if (!pos->son[ID(s[i])]) pos->son[ID(s[i])]=new node(0,++si);            pos=pos->son[ID(s[i])];pos->w++;            int num=pos->que.size();            if (!num||pos->w>num) pos->que.push_back(te);            //新的w出现了,把事件编号加入vector        }    }    void Delete(char *s)    {        P_node pos=ro;        for (int i=1;s[i];i++) pos=pos->son[ID(s[i])],pos->w--;    }    int Find(char *s,int v)    {        P_node pos=ro;        for (int i=1;s[i];i++)            if (!pos->son[ID(s[i])]) return -1; else            pos=pos->son[ID(s[i])];        int num=pos->que.size();        if (num<=v) return -1;        return pos->que[v]; //输出v+1的最小事件编号    }};Trie tr;char readc(){    static char buf[100000],*l=buf,*r=buf;    if (l==r) r=(l=buf)+fread(buf,1,100000,stdin);    if (l==r) return EOF; else return *l++;}bool Eoln(char ch) {return ch==10||ch==13||ch==EOF;}int reads(char *s){    int len=0;char ch=readc();if (ch==EOF) return EOF;    s[++len]=ch;while ('a'<=s[len]&&s[len]<='z') s[++len]=readc();    s[len--]=0;return len;}int readi(int &x){    int tot=0,f=1;char ch=readc(),lst=ch;    while ('9'<ch||ch<'0') {if (ch==EOF) return EOF;lst=ch;ch=readc();}    if (lst=='-') f=-f;    while ('0'<=ch&&ch<='9') tot=tot*10+ch-48,ch=readc();    x=tot*f;    return Eoln(ch);}int absi(int x) {if (x<0) return -x; else return x;}int main(){    freopen("program.in","r",stdin);    freopen("program.out","w",stdout);    readi(te);    for (int i=1;i<=te;i++)    {        int td;readi(td);reads(s);        if (td==1) tr.Insert(s,i); else        if (td==2) tr.Delete(s); else        {            int a,b,c;readi(a);readi(b);readi(c);            printf("%d\n",ans=tr.Find(s,((LL)a*absi(ans)+b)%c));        }    }    return 0;}
阅读全文
0 0
原创粉丝点击