字符串:SAM

HDU4622:区间查询不同子串个数

用后缀自动机预处理出所有区间的不同子串个数

建立n次后缀自动机

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <algorithm>
  4 #include <iostream>
  5 using namespace std;
  6 
  7 const int CHAR = 26;
  8 const int MAXN = 2020;
  9 struct SAM_Node
 10 {
 11     SAM_Node *fa,*next[CHAR];
 12     int len;
 13     int id,pos;
 14     SAM_Node(){}
 15     SAM_Node(int _len)
 16     {
 17         fa = 0;
 18         len = _len;
 19         memset(next,0,sizeof(next));
 20     }
 21 };
 22 SAM_Node SAM_node[MAXN*2], *SAM_root, *SAM_last;
 23 int SAM_size;
 24 SAM_Node *newSAM_Node(int len)
 25 {
 26     SAM_node[SAM_size] = SAM_Node(len);
 27     SAM_node[SAM_size].id = SAM_size;
 28     return &SAM_node[SAM_size++];
 29 }
 30 SAM_Node *newSAM_Node(SAM_Node *p)
 31 {
 32     SAM_node[SAM_size] = *p;
 33     SAM_node[SAM_size].id = SAM_size;
 34     return &SAM_node[SAM_size++];
 35 }
 36 void SAM_init()
 37 {
 38     SAM_size = 0;
 39     SAM_root = SAM_last = newSAM_Node(0);
 40     SAM_node[0].pos = 0;
 41 }
 42 void SAM_add(int x,int len)
 43 {
 44     SAM_Node *p = SAM_last, *np = newSAM_Node(p->len+1);
 45     np->pos = len;
 46     SAM_last = np;
 47     for(;p && !p->next[x];p = p->fa)
 48         p->next[x] = np;
 49     if(!p)
 50     {
 51         np->fa = SAM_root;
 52         return;
 53     }
 54     SAM_Node *q = p->next[x];
 55     if(q->len == p->len + 1)
 56     {
 57         np->fa = q;
 58         return;
 59     }
 60     SAM_Node *nq = newSAM_Node(q);
 61     nq->len = p->len + 1;
 62     q->fa = nq;
 63     np->fa = nq;
 64     for(;p && p->next[x] == q;p = p->fa)
 65         p->next[x] = nq;
 66 }
 67 void SAM_build(char *s)
 68 {
 69     SAM_init();
 70     int len = strlen(s);
 71     for(int i = 0;i < len;i++)
 72         SAM_add(s[i] - 'a',i+1);
 73 }
 74 
 75 int Q[MAXN][MAXN];
 76 char str[MAXN];
 77 int main()
 78 {
 79     int T;
 80     scanf("%d",&T);
 81     while(T--)
 82     {
 83         scanf("%s",str);
 84         int n = strlen(str);
 85         memset(Q,0,sizeof(Q));
 86         for(int i = 0;i < n;i++)
 87         {
 88             SAM_init();
 89             for(int j = i;j < n;j++)
 90             {
 91                 SAM_add(str[j]-'a',j-i+1);
 92             }
 93             for(int j = 1;j < SAM_size;j++)
 94             {
 95                 Q[i][SAM_node[j].pos-1+i]+=SAM_node[j].len - SAM_node[j].fa->len;
 96             }
 97             for(int j = i+1;j < n;j++)
 98                 Q[i][j] += Q[i][j-1];
 99         }
100         int M;
101         int u,v;
102         scanf("%d",&M);
103         while(M--)
104         {
105             scanf("%d%d",&u,&v);
106             u--;v--;
107             printf("%d
",Q[u][v]);
108         }
109     }
110     return 0;
111 }

此题也有字符串哈希做法

没看懂就不贴了

原文地址:https://www.cnblogs.com/aininot260/p/9636591.html