• 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 }
  • 相关阅读:
    ubuntu20.04上实现百度Apollo6.0系统的部署
    matplotlib包图例出现中文乱码问题
    微软官方Silverlight 音频播放器 Jonas修整版(silerlight 2.0版)
    SpringCloud总结1
    Java中文长度计算
    注册退出函数:atexit
    函数参数的一种特殊用法
    new与malloc等的区别
    两种多态
    第一章 1.1.2 因特网提供服务的方式
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/4590730.html
Copyright © 2020-2023  润新知