• 后缀自动机


    模板

     1 struct SAM{
     2     static const int MAXN = 100001<<1;//大小为字符串长度两倍
     3     static const int LetterSize = 26;
     4 
     5     int tot, last, ch[MAXN][LetterSize], fa[MAXN], len[MAXN];
     6     int sum[MAXN], tp[MAXN], cnt[MAXN]; //sum,tp用于拓扑排序,tp为排序后的数组
     7     //tp 长度拓扑序后的位置
     8     //cnt
     9     /*1.对于每个节点,父节点的接受串是该节点的接受串的后缀,而且是最长的那个。
    10     所以呢,用该节点的len减去父节点的fa.len,就是该节点表示的串中父节点不能表示的串个数。
    11     当某节点的计数到达k次时,就说明有len-fa.len个不同子串计数到达k次了。
    12     (同理,当插入这个节点,出现的新不同子串个数就是len-fa.len。这也是很有用的性质。)
    13 
    14     2.每个节点表示串出现的次数,是这个节点子树上有效节点的总数。
    15     (有效节点指插入该字符产生的那个节点,也就是代码中extend中的np节点)。
    16     这样我们初始化有效节点为1,然后拓扑排序dp,就可以O(n)得到每个节点出现次数。*/
    17     void init( void){
    18         last = tot = 1;
    19         len[1] = 0;
    20         memset(ch,0,sizeof ch);
    21         memset(fa,0,sizeof fa);
    22         memset(cnt,0,sizeof cnt);
    23     }
    24 
    25     void add( int x){
    26         int p = last, np = last = ++tot;
    27         len[np] = len[p] + 1, cnt[last] = 1;
    28         memset( ch[np], 0, sizeof ch[np]);
    29         while( p && !ch[p][x]) ch[p][x] = np, p = fa[p];
    30         if( p == 0)
    31             fa[np] = 1;
    32         else{
    33             int q = ch[p][x];
    34             if( len[q] == len[p] + 1)
    35                 fa[np] = q;
    36             else{
    37                 int nq = ++tot;
    38                 memcpy( ch[nq], ch[q], sizeof ch[q]);
    39                 len[nq] = len[p] + 1, fa[nq] = fa[q], fa[q] = fa[np] = nq;
    40                 while( p && ch[p][x] == q)  ch[p][x] = nq, p = fa[p];
    41             }
    42         }
    43     }
    44 
    45     void toposort(){
    46         for(int i = 1; i <= len[last]; i++)   sum[i] = 0;
    47         for(int i = 1; i <= tot; i++)   sum[len[i]]++;
    48         for(int i = 1; i <= len[last]; i++)   sum[i] += sum[i-1];
    49         for(int i = 1; i <= tot; i++)   tp[sum[len[i]]--] = i;
    50         for(int i = tot; i; i--)   cnt[fa[tp[i]]] += cnt[tp[i]];
    51     }
    52 
    53 } sam;
  • 相关阅读:
    HTML5 文件上传
    Vue-Router模式、钩子
    网络基础协议随笔
    Vue-Router基础使用
    vue中mixin的一点理解
    纯css3跑马灯demo
    Charles使用笔记
    提个醒。。。
    本机未装Oracle数据库时Navicat for Oracle 报错:Cannot create oci environment 原因分析及解决方案
    easyUI datagrid 清空
  • 原文地址:https://www.cnblogs.com/yZiii/p/7677961.html
Copyright © 2020-2023  润新知