zoukankan      html  css  js  c++  java
  • HDU-4622 Reincarnation (后缀自动机)

    题意:给定一个字符串,多组询问,每个询问给一个区间,求出该区间内共有多少个不同的子串。

    这题就是查询一个区间内的不同子串的个数。

    如果单单是求一个字符串的不同子串个数,无论是后缀数组还是后缀自动机都非常容易实现。

    N<=2000.

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

    建立n次后缀自动机。

    后缀自动机要理解其含义,从起点到每个点的不同路径,就是不同的子串。

    到每一个点,不同路径,其实就是以这个点为最后一个字符的后缀,长度是介于(p->fa->len,p->len]之间的,个数也就清楚了。

    而且这个其实是动态变化的,每加入一个字符,就可以知道新加了几个不同子串。

    加个pos,记录位置,这样就很容易预处理了。

      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 }
  • 相关阅读:
    Codeforces Round #649 (Div. 2) D. Ehab's Last Corollary
    Educational Codeforces Round 89 (Rated for Div. 2) E. Two Arrays
    Educational Codeforces Round 89 (Rated for Div. 2) D. Two Divisors
    Codeforces Round #647 (Div. 2) E. Johnny and Grandmaster
    Codeforces Round #647 (Div. 2) F. Johnny and Megan's Necklace
    Codeforces Round #648 (Div. 2) G. Secure Password
    Codeforces Round #646 (Div. 2) F. Rotating Substrings
    C++STL常见用法
    各类学习慕课(不定期更新
    高阶等差数列
  • 原文地址:https://www.cnblogs.com/agenthtb/p/7696220.html
Copyright © 2011-2022 走看看