zoukankan      html  css  js  c++  java
  • spoj 7258 SUBLEX(SAM,名次)

    【题目链接】

      http://www.spoj.com/problems/SUBLEX/en/

    【题意】

           给定一个字符串,询问次序为k的子串。

    【思路】

      SAM,名次

      建好SAM后求出每个结点根据trans转移向下统计有多少与该结点有相同前缀的子串,每个结点只算一个,因为该结点所代表的字符串集中只可能有一个与上面统计下来的字符串前缀相同,其他的字符串都与该字符串为后缀关系。

      设sum(p)为与root->p有相同前缀的字符串,设np=trans(p,x),则有转移式:

        sum(p)=sigma{ sum(np) }

      找名次为k的子串,只需要按照sum进行转移即可。

    【代码】

     1 #include<cstdio>
     2 #include<cstring>
     3 using namespace std;
     4 
     5 const int N = 3*1e5+10;
     6 
     7 char s[N];
     8 int root,last,sz,ch[N][26],fa[N],sum[N],l[N];
     9 void add(int x) {
    10     int c=s[x]-'a';
    11     int p=last,np=++sz; last=np;
    12     l[np]=x+1;
    13     for(;p&&!ch[p][c];p=fa[p]) ch[p][c]=np;
    14     if(!p) fa[np]=root;
    15     else {
    16         int q=ch[p][c];
    17         if(l[p]+1==l[q]) fa[np]=q;
    18         else {
    19             int nq=++sz; l[nq]=l[p]+1;
    20             memcpy(ch[nq],ch[q],sizeof(ch[q]));
    21             fa[nq]=fa[q];
    22             fa[np]=fa[q]=nq;
    23             for(;p&&q==ch[p][c];p=fa[p]) ch[p][c]=nq;
    24         }
    25     }
    26 }
    27 
    28 int n,m,b[N],cnt[N];
    29 
    30 void get_sum() {
    31     for(int i=1;i<=sz;i++) cnt[l[i]]++;
    32     for(int i=1;i<=n;i++) cnt[i]+=cnt[i-1];
    33     for(int i=1;i<=sz;i++) b[cnt[l[i]]--]=i;
    34     for(int i=sz;i;i--) {
    35         int p=b[i]; sum[p]=1;
    36         for(int j=0;j<26;j++)
    37             sum[p]+=sum[ch[p][j]];
    38     }
    39 }
    40 
    41 int main() {
    42     scanf("%s",s);
    43     n=strlen(s);
    44     root=last=++sz;
    45     for(int i=0;i<n;i++) add(i);
    46     get_sum();
    47     scanf("%d",&m);
    48     while(m--) {
    49         int x,p=root; scanf("%d",&x);
    50         while(x) {
    51             for(int c=0;c<26;c++)if(ch[p][c]) {
    52                 if(sum[ch[p][c]]>=x) {
    53                     putchar('a'+c);
    54                     x--; p=ch[p][c];
    55                     break;
    56                 }
    57                 else x-=sum[ch[p][c]];
    58             }
    59         }
    60         puts("");
    61     }
    62     return 0;
    63 }
  • 相关阅读:
    词法分析程序~总结
    0916 词法分析程序
    0909 编译原理
    1029 文法分析
    0916 编译原理第二次上机作业
    0909 编译原理第一次上机作业
    复利计算之回顾并总结这三次实验
    复利计算之说明代码运行结果和功能点
    操作系统之实验0 了解和熟悉操作系统
    12-16 实验四 递归下降语法分析程序设计
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5198797.html
Copyright © 2011-2022 走看看