zoukankan      html  css  js  c++  java
  • CC TSUBSTR:Substrings on a Tree——题解

    https://www.codechef.com/problems/TSUBSTR

    https://vjudge.net/problem/CodeChef-TSUBSTR

    给一棵点权为字母的树,你只能从任意节点往下走得到一个字符串,求出可得到的不重复字符串数量和其中字典序第k小的字符串(在重新定义字母的字典序前提下)?

    垃圾谷歌翻译坑我不浅。

    广义后缀自动机处理之后就是BZOJ3998:[TJOI2015]弦论t=0的解法了。

    注意空字符串也算。

    #include<cstdio>
    #include<iostream>
    #include<queue>
    #include<cstring>
    #include<algorithm>
    #include<cctype>
    using namespace std;
    typedef long long ll;
    const int N=2e6+5;
    struct tree{
        int a[26],fa,l;
    }tr[N];
    struct node{
        int to,nxt;
    }e[N];
    char s[N];
    int tot,cnt,head[N],pos[N];
    ll a[N],w[N],size[N],sum[N];
    bool vis[N];
    queue<int>q;
    inline void add(int u,int v){
        e[++cnt].to=v;e[cnt].nxt=head[u];head[u]=cnt;
    }
    inline int insert(int p,int c){
        int np=tr[p].a[c];
        if(np&&tr[np].l==tr[p].l+1)return np;
        np=++tot;tr[np].l=tr[p].l+1;
        for(;p&&!tr[p].a[c];p=tr[p].fa)tr[p].a[c]=np;
        if(!p)tr[np].fa=1;
        else{
        int q=tr[p].a[c];
        if(tr[p].l+1==tr[q].l)tr[np].fa=q;
        else{
            int nq=++tot;tr[nq].l=tr[p].l+1;
            memcpy(tr[nq].a,tr[q].a,sizeof(tr[q].a));
            tr[nq].fa=tr[q].fa;tr[q].fa=tr[np].fa=nq;
            for(;p&&tr[p].a[c]==q;p=tr[p].fa)tr[p].a[c]=nq;
        }
        }
        return np;
    }
    void bfs(int st){
        tot=1;
        q.push(st);vis[st]=1;
        pos[st]=insert(1,s[st]-'a');
        while(!q.empty()){
        int u=q.front();q.pop();
        for(int i=head[u];i;i=e[i].nxt){
            int v=e[i].to;
            if(vis[v])continue;
            q.push(v);vis[v]=1;
            pos[v]=insert(pos[u],s[v]-'a');
        }
        }
    }
    int main(){
        int len,q;
        scanf("%d%d",&len,&q);
        scanf("%s",s+1);
        for(int i=1;i<len;i++){
        int u,v;
        scanf("%d%d",&u,&v);
        add(u,v);add(v,u);
        }
        bfs(1);
        for(int i=1;i<=tot;i++)w[tr[i].l]++;
        for(int i=1;i<=len;i++)w[i]+=w[i-1];
        for(int i=1;i<=tot;i++)a[w[tr[i].l]--]=i;
        for(int i=tot;i>=1;i--){
        size[a[i]]=1;
        }
        for(int i=tot;i>=1;i--){
        sum[a[i]]=size[a[i]];
        for(int j=0;j<26;j++)
            if(tr[a[i]].a[j])sum[a[i]]+=sum[tr[a[i]].a[j]];
        }
        printf("%lld
    ",sum[1]);
        for(int i=1;i<=q;i++){
        ll k;
        scanf("%s%lld",s,&k);
        if(k>sum[1]){puts("-1");continue;}
        int now=1;
        while(k>size[now]){
            k-=size[now];
            for(int j=0;j<26;j++){
            if(k>sum[tr[now].a[s[j]-'a']]){
                k-=sum[tr[now].a[s[j]-'a']];
            }else{
                now=tr[now].a[s[j]-'a'];
                putchar(s[j]);
                break;
            }
            }
        }
        puts("");
        }
        return 0;
    }

    +++++++++++++++++++++++++++++++++++++++++++

    +本文作者:luyouqi233。               +

    +欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

    +++++++++++++++++++++++++++++++++++++++++++

  • 相关阅读:
    mysql 每条数据增加随机数
    Linux 的VSFTP报错
    Linux 常见命令指南
    Python文件
    Python合并2个文件
    J2ME获取移动手机号码
    不同角度来理解面向对象的几个关键性概念
    打印字符串中第一个只出现一次的字符(C语言)
    ftp上传文件
    ftp上传到nas
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/8794800.html
Copyright © 2011-2022 走看看