jzoj 5795 词典

题目

这里写图片描述这里写图片描述


题解

–这道题我竟然在考场上想出来了正解(笑cry)
这道题不是什么hash,就是一个Trie,可以在每个节点用一个vector存答案,最后查询就是了
但是,当时我vector用太多了,不仅调试慢,而且可能爆空间
所以来优化一下
发现,对于每个节点其实没必要存下所有答案的位置,他为零的区间长度其实只和
当前位置-上次位置-1有关,所以说我们只需要记录上次出现的位置,并且同时维护最长区间长度
不仅建变快了,查询也变快了

这道题还有个神坑,就是这道题的数据是在Windows下生成的,所以换行符是\r\n,
而评测环境是Linux,换行符就是\n,
所以每次要用两个getchar()读取换行(QAQ就是这个一直卡我)


代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int MAXN=5*1e6+5;

int n,m;
char t,s;

struct hehe{
    int ans;
    int last;
    int a;
    int b;
    int c;
}tree[MAXN];
int cnt;
int ans[100005];

void add(int x,int y){
    int v;
    t=getchar();
    if(t=='a'){
        if(!tree[x].a)
            tree[x].a=++cnt;
        v=tree[x].a;
        tree[v].ans=max(tree[v].ans,y-tree[v].last-1);
        tree[v].last=y;
        add(v,y);
    }
    else if(t=='b'){
        if(!tree[x].b)
            tree[x].b=++cnt;
        v=tree[x].b;
        tree[v].ans=max(tree[v].ans,y-tree[v].last-1);
        tree[v].last=y;
        add(v,y);
    }
    else if(t=='c'){
        if(!tree[x].c)
            tree[x].c=++cnt;
        v=tree[x].c;
        tree[v].ans=max(tree[v].ans,y-tree[v].last-1);
        tree[v].last=y;
        add(v,y);
    }
    else
        return ;
}

int Find(int x){
    int v;
    s=getchar();
    if(s=='a'){
        v=tree[x].a;
        if(!v)
            return n;
        return Find(v);
    }
    else if(s=='b'){
        v=tree[x].b;
        if(!v)
            return n;
        return Find(v);
    }
    else if(s=='c'){
        v=tree[x].c;
        if(!v)
            return n;
        return Find(v);
    }
    else
        return max(tree[x].ans,n-tree[x].last);
}

int main(){
    freopen("word.in","r",stdin);
    freopen("word.out","w",stdout);
    cin>>n>>m;
    getchar();
    getchar();
    for(int i=1;i<=n;i++){
        add(0,i);
        getchar();
    }
    for(int i=1;i<=m;i++){
        ans[i]=Find(0);
        while(s=='a'||s=='b'||s=='c')
            s=getchar();
        getchar();
    }
    for(int i=1;i<=m;i++)
        printf("%d\n",ans[i]);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值