后缀自动机模板 SAM

一点疑问:

  当创建nq节点时,要不要把nq的cnt标记赋值为1?

  讲道理nq节点也是代表一个子串啊,不过网上的模板都没赋值。

2017.9.18 update:

  把memset部分重写,改成用节点用到时再初始化,初始化所有节点可能被卡。

  fa,len,cnt数组其实不用清空,因为用时都赋值了。

 1 struct SAM
 2 {
 3     static const int MAXN = 300001<<1;//大小为字符串长度两倍
 4     static const int LetterSize = 26;
 5 
 6     int tot, last, ch[MAXN][LetterSize], fa[MAXN], len[MAXN];
 7     int sum[MAXN], tp[MAXN], cnt[MAXN]; //sum,tp用于拓扑排序,tp为排序后的数组
 8 
 9     void init( void)
10     {
11         last = tot = 1;
12         len[1] = 0;
13         memset( ch[1], 0, sizeof ch[1]);
14     }
15 
16     void add( int x)
17     {
18         int p = last, np = last = ++tot;
19         len[np] = len[p] + 1, cnt[last] = 1;
20         memset( ch[np], 0, sizeof ch[np]);
21         while( p && !ch[p][x]) ch[p][x] = np, p = fa[p];
22         if( p == 0)
23             fa[np] = 1;
24         else
25         {
26             int q = ch[p][x];
27             if( len[q] == len[p] + 1)
28                 fa[np] = q;
29             else
30             {
31                 int nq = ++tot;
32                 memcpy( ch[nq], ch[q], sizeof ch[q]);
33                 len[nq] = len[p] + 1, fa[nq] = fa[q], fa[q] = fa[np] = nq;
34                 while( p && ch[p][x] == q)  ch[p][x] = nq, p = fa[p];
35             }
36         }
37     }
38 
39     void toposort( void)
40     {
41         for(int i = 1; i <= len[last]; i++)   sum[i] = 0;
42         for(int i = 1; i <= tot; i++)   sum[len[i]]++;
43         for(int i = 1; i <= len[last]; i++)   sum[i] += sum[i-1];
44         for(int i = 1; i <= tot; i++)   tp[sum[len[i]]--] = i;
45         for(int i = tot; i; i--)   cnt[fa[tp[i]]] += cnt[tp[i]];
46     }
47 } sam;

 

posted @ 2017-09-13 17:21  weeping  阅读(771)  评论(0编辑  收藏  举报