zoukankan      html  css  js  c++  java
  • BZOJ3439: Kpm的MC密码

    3439: Kpm的MC密码

    Time Limit: 15 Sec  Memory Limit: 256 MB
    Submit: 166  Solved: 79
    [Submit][Status]

    Description


     背景

        想Kpm当年为了防止别人随便进入他的MC,给他的PC设了各种奇怪的密码和验证问题(不要问我他是怎么设的。。。),于是乎,他现在理所当然地忘记了密码,只能来解答那些神奇的身份验证问题了。。。

     描述

        Kpm当年设下的问题是这样的:

        现在定义这么一个概念,如果字符串s是字符串c的一个后缀,那么我们称c是s的一个kpm串。

        系统将随机生成n个由a…z组成的字符串,由1…n编号(s1,s2…,sn),然后将它们按序告诉你,接下来会给你n个数字,分别为k1…kn,对于每一个ki,要求你求出列出的n个字符串中所有是si的kpm串的字符串的编号中第ki小的数,如果不存在第ki小的数,则用-1代替。(比如说给出的字符串是cd,abcd,bcd,此时k1=2,那么”cd”的kpm串有”cd”,”abcd”,”bcd”,编号分别为1,2,3其中第2小的编号就是2)(PS:如果你能在相当快的时间里回答完所有n个ki的查询,那么你就可以成功帮kpm进入MC啦~~)

    Input

        第一行一个整数 n 表示字符串的数目

        接下来第二行到n+1行总共n行,每行包括一个字符串,第i+1行的字符串表示编号为i的字符串

        接下来包括n行,每行包括一个整数ki,意义如上题所示

    Output

        包括n行,第i行包括一个整数,表示所有是si的kpm串的字符串的编号中第ki小的数

    Sample Input


    3
    cd
    abcd
    bcd
    2
    3
    1

    Sample Output

    2
    -1
    2

    样例解释

    “cd”的kpm 串有”cd”,”abcd”,”bcd”,编号为1,2,3,第2小的编号是

    2,”abcd”的kpm串只有一个,所以第3小的编号不存在,”bcd”的kpm

    串有”abcd”,”bcd”,第1小的编号就是2。

    数据范围与约定

    设所有字符串的总长度为len


    对于100%的数据,1<=n<=100000,0<len<=300000

    HINT

     

    Source

    题解:
    真是一道好题!
    很容易想到把字符串反转之后插入一棵trie树,然后s的kpm串就是它的子树,然后dfs序处理一下把子树内的信息变成连续的就可以用主席树求第k小了。
    刚开始把kpm串的定义看反了,然后就把每个点到根节点的主席树建了出来。。。
    实现的时候有很多细节,我参考了某大牛的代码
    代码:
      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<iostream>
      4 #include<algorithm>
      5 #include<cstring>
      6 #include<queue>
      7 #include<vector>
      8 #include<map>
      9 #include<set>
     10 #include<stack>
     11 #include<string>
     12 #include<cmath>
     13 #include<cctype>
     14 using namespace std;
     15 const int maxlongint=2147483647;
     16 const int inf=1000000000;
     17 int trie[300010][26],o=1,fa[300010];
     18 vector<int> en[300010];
     19 int nx[100010];
     20 char a[300010];
     21 int root[600010];
     22 int lch[4000010],rch[4000010],num[4000010],x=0;
     23 int dfn[300010][2],now=0,n;
     24 int insert(int i,int l,int r,int j)
     25 {
     26     x++;
     27     int t=x;
     28     lch[t]=lch[i];
     29     rch[t]=rch[i];
     30     num[t]=num[i]+1;
     31     if(l!=r)
     32     {
     33         int mid=(l+r)>>1;
     34         if(j>mid)
     35             rch[t]=insert(rch[i],mid+1,r,j);
     36         else
     37             lch[t]=insert(lch[i],l,mid,j);
     38     }
     39     return t;
     40 }
     41 int dfs(int i)
     42 {
     43     int n1;
     44     now++;
     45     int sz=en[i].size(),rt=root[now-1];
     46     for(n1=0;n1<sz;n1++)
     47         rt=insert(rt,1,n,en[i][n1]);
     48     root[now]=rt;
     49     dfn[i][0]=now;
     50     for(n1=0;n1<26;n1++)
     51         if(trie[i][n1])
     52             dfs(trie[i][n1]);
     53     now++;
     54     dfn[i][1]=now;
     55     root[now]=root[now-1];
     56 }
     57 int get(int i,int j,int k)
     58 {
     59     i=root[i-1],j=root[j];
     60     if(num[j]-num[i]<k)
     61         return -1;
     62     int l=1,r=n;
     63     while(l!=r)
     64     {
     65         int mid=(l+r)>>1;
     66         if(num[lch[j]]-num[lch[i]]>=k)
     67         {
     68             r=mid;
     69             i=lch[i];
     70             j=lch[j];
     71         }
     72         else
     73         {
     74             k-=num[lch[j]]-num[lch[i]];
     75             l=mid+1;
     76             i=rch[i];
     77             j=rch[j];
     78         }
     79     }
     80     return l;
     81 }
     82 int main()
     83 {
     84     int n1,n2;
     85     cin>>n;
     86     for(n1=1;n1<=n;n1++)
     87     {
     88         scanf("%s",a);
     89         int len=strlen(a);
     90         for(n2=0;n2<=(len-2)/2;n2++)
     91             swap(a[n2],a[len-n2-1]);
     92         int p=1;
     93         for(n2=0;n2<len;n2++)
     94         {
     95             if(trie[p][a[n2]-97]==0)
     96             {
     97                 o++;
     98                 trie[p][a[n2]-97]=o;
     99                 fa[o]=p;
    100             }
    101             p=trie[p][a[n2]-97];
    102             if(n2==len-1)
    103             {
    104                 nx[n1]=p;
    105                 en[p].push_back(n1);
    106             }
    107         }
    108     }
    109     dfs(1);
    110     int t1;
    111     for(n1=1;n1<=n;n1++)
    112     {
    113         scanf("%d",&t1);
    114         printf("%d
    ",get(dfn[nx[n1]][0],dfn[nx[n1]][1],t1));
    115     }
    116 }
    View Code

    我的:TLE

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<algorithm>
     6 #include<iostream>
     7 #include<vector>
     8 #include<map>
     9 #include<set>
    10 #include<queue>
    11 #include<string>
    12 #define inf 1000000000
    13 #define maxn 1000000+5
    14 #define maxm 5000000
    15 #define eps 1e-10
    16 #define ll long long
    17 #define pa pair<int,int>
    18 #define for0(i,n) for(int i=0;i<=(n);i++)
    19 #define for1(i,n) for(int i=1;i<=(n);i++)
    20 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
    21 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
    22 #define mod 1000000007
    23 using namespace std;
    24 inline int read()
    25 {
    26     int x=0,f=1;char ch=getchar();
    27     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    28     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
    29     return x*f;
    30 }
    31 int n,m,cnt=1,tot,now,s[maxm],ls[maxm],rs[maxm],t[maxn][26],rt[maxn],dfn[maxn][2],p[maxn];
    32 vector<int>G[maxn];
    33 char st[maxn];
    34 void update(int l,int r,int x,int &y,int z)
    35 {
    36     y=++tot;
    37     s[y]=s[x]+1;
    38     if(l==r)return;
    39     ls[y]=ls[x];rs[y]=rs[x];
    40     int mid=(l+r)>>1;
    41     if(z<=mid)update(l,mid,ls[x],ls[y],z);else update(mid+1,r,rs[x],rs[y],z);
    42 }
    43 void dfs(int x)
    44 {
    45     dfn[x][0]=++now;
    46     int sz=G[x].size(),y=rt[now-1],yy=y;
    47     for0(i,sz-1)update(1,n,y,yy,G[x][i]),y=yy;
    48     rt[now]=yy;
    49     for0(i,25)if(t[x][i])dfs(t[x][i]);
    50     dfn[x][1]=++now;
    51     rt[now]=rt[now-1];
    52 }
    53 int query(int x,int y,int k)
    54 {
    55     int l=1,r=n,xx=rt[x-1],yy=rt[y];
    56     if(s[yy]-s[xx]<k)return -1;
    57     while(l!=r)
    58     {
    59         int mid=(l+r)>>1;
    60         if(s[ls[yy]]-s[ls[xx]]>=k){xx=ls[xx];yy=ls[yy];r=mid;}
    61         else {k-=s[ls[yy]]-s[ls[xx]];xx=rs[xx];yy=rs[yy];l=mid+1;}
    62     }
    63     return l;
    64 }
    65 int main()
    66 {
    67     freopen("input.txt","r",stdin);
    68     freopen("output.txt","w",stdout);
    69     n=read();
    70     for1(i,n)
    71     {
    72         memset(st,0,sizeof(st));
    73         scanf("%s",st+1);m=strlen(st+1);
    74         now=1;
    75         for3(j,m,1)
    76         {
    77             int x=st[j]-'a';
    78             if(!t[now][x])t[now][x]=++cnt;
    79             now=t[now][x];
    80         }
    81         p[i]=now;G[now].push_back(i);
    82     }
    83     now=0;
    84     dfs(1);
    85     for1(i,n)
    86     {
    87         int k=read();
    88         printf("%d
    ",query(dfn[p[i]][0],dfn[p[i]][1],k));
    89     }
    90     return 0;
    91 }
    View Code
  • 相关阅读:
    MVC上传文件并模拟进度条
    C#文件的压缩和解压(ZIP)使用DotNetZip封装类操作zip文件(创建/读取/更新)实例
    Inherits、CodeFile、CodeBehind的区别
    .csproj文件的配置 IIS可以调试
    C# <%@ Register %>指令
    将n行3列的数据dataTable装换成m行7列的dataTable
    在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误。未找到或无法访问服务器。请验证实例名称是否正确并且 SQL Server 已配置为允许远程连接。 (provider: 命名管道提供程序, error: 40
    Js全选,插入实现
    Jquery autocomplete插件的使用
    jquery.autocomplete自动补全功能
  • 原文地址:https://www.cnblogs.com/zyfzyf/p/4100346.html
Copyright © 2011-2022 走看看