• SPOJ NSUBSTR


     题目大意:

    给定一个字符串,求每个对应的长度能产生的相同子串的最大个数

    这里构建好后缀自动机之后,再将整个字符串从头到尾扫一遍,然后将每个对应的点上的sc值+1

    表示从头走到尾的前提下,所能产生的子串能够得到的最大数量为1

    然后再去考虑其他子串

    每个后缀自动机上的节点上的长度表示的是当前点所能接收的最大长度的后缀

    我们只考虑这个最大长度即可,因为其他没考虑的长度,最后都不断通过dp[i] = max(dp[i] , dp[i+1]) 得到即可

    拓扑排序后,从尾节点开始不断往前,相当于由子节点不断更新父节点所能得到的值

    也就是b[i]->f->sc += b[i]->sc;

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 
     5 using namespace std;
     6 #define N 500010
     7 #define M 26
     8 
     9 struct SamNode{
    10     SamNode *son[26] , *f;
    11     int l , sc;
    12 }*root , *last , sam[N] , *b[N];
    13 
    14 int cnt , dp[N] , num[N];
    15 char s[N];
    16 
    17 void init(){
    18     root = last = &sam[cnt=0];
    19 }
    20 
    21 void add(int x)
    22 {
    23     SamNode *p = &sam[++cnt] , *jp=last;
    24     p->l = jp->l+1;
    25     last = p;
    26     for( ; jp&&!jp->son[x] ; jp=jp->f) jp->son[x]=p;
    27     if(!jp) p->f = root;
    28     else{
    29         if(jp->l+1 == jp->son[x]->l) p->f = jp->son[x];
    30         else{
    31             SamNode *r = &sam[++cnt] , *q = jp->son[x];
    32             *r = *q;
    33             r->l = jp->l+1;
    34             q->f = p->f = r;
    35             for( ; jp && jp->son[x]==q ; jp=jp->f) jp->son[x]=r;
    36         }
    37     }
    38 }
    39 
    40 
    41 void solve()
    42 {
    43     init();
    44     int len = strlen(s);
    45     for(int i=0 ; i<len ; i++) add(s[i]-'a');
    46     //后面三个for循环相当于进行拓扑排序
    47     for(int i=0 ; i<=cnt ; i++) num[sam[i].l]++;
    48     for(int i=1 ; i<=len ; i++) num[i]+=num[i-1];
    49     for(int i=0 ; i<=cnt ; i++) b[--num[sam[i].l]] = &sam[i];
    50 
    51     SamNode *cur = root;
    52     for(int i=0 ; i<len ; i++){
    53         cur = cur->son[s[i]-'a'];
    54         cur->sc++;
    55     }
    56     for(int i=cnt ; i>0 ; i--){
    57         int l = b[i]->l;
    58         dp[l] = max(dp[l] , b[i]->sc);
    59         b[i]->f->sc += b[i]->sc;
    60     }
    61     for(int i=len-1 ; i>=1 ; i--) dp[i]=max(dp[i] , dp[i+1]);
    62     for(int i=1 ; i<=len ; i++) printf("%d
    " , dp[i]);
    63 }
    64 
    65 int main()
    66 {
    67    // freopen("a.in" , "r" , stdin);
    68     scanf("%s" , s);
    69     solve();
    70     return 0;
    71 }
  • 相关阅读:
    Centos 7 zabbix 实战应用
    Centos7 Zabbix添加主机、图形、触发器
    Centos7 Zabbix监控部署
    Centos7 Ntp 时间服务器
    Linux 150命令之查看文件及内容处理命令 cat tac less head tail cut
    Kickstart 安装centos7
    Centos7与Centos6的区别
    Linux 150命令之 文件和目录操作命令 chattr lsattr find
    Linux 发展史与vm安装linux centos 6.9
    Linux介绍
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/4590730.html
Copyright © 2020-2023  润新知