zoukankan      html  css  js  c++  java
  • hdu4622(后缀自动机模板)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4622

    题意: 先输入一个长度为 n 的字符串, 然后有 q 个形如 l, r 的询问, 对于每个询问输出区间 [l, r] 中有多少不同的子串

    思路: 后缀自动机模板

    代码:

      1 // 后缀自动机要理解其含义,从起点到每个点的不同路径,就是不同的子串。
      2 // 到每一个点,不同路径,其实就是以这个点为最后一个字符的后缀,长度是介于(p->fa->len,p->len]之间的,个数也就清楚了。
      3 // 而且这个其实是动态变化的,每加入一个字符,就可以知道新加了几个不同子串。
      4 // 加个pos,记录位置,这样就很容易预处理了。
      5 
      6 #include <iostream>
      7 #include <stdio.h>
      8 #include <string.h>
      9 using namespace std;
     10 
     11 const int CHAR = 26;
     12 const int MAXN = 2e3 + 10;
     13 
     14 struct SAM_Node{
     15     SAM_Node *fa, *next[CHAR];
     16     int len, id, pos;
     17     SAM_Node(){};
     18     SAM_Node(int _len){
     19         fa = 0;
     20         len = _len;
     21         memset(next, 0, sizeof(next));
     22     }
     23 };
     24 
     25 SAM_Node SAM_node[MAXN << 1], *SAM_root, *SAM_last;
     26 int SAM_size;
     27 
     28 SAM_Node *newSAM_Node(int len){
     29     SAM_node[SAM_size] = SAM_Node(len);
     30     SAM_node[SAM_size].id = SAM_size;
     31     return &SAM_node[SAM_size++];
     32 }
     33 
     34 SAM_Node *newSAM_Node(SAM_Node *p){
     35     SAM_node[SAM_size] = *p;
     36     SAM_node[SAM_size].id = SAM_size;
     37     return &SAM_node[SAM_size++];
     38 }
     39 
     40 void SAM_init(void){
     41     SAM_size = 0;
     42     SAM_root = SAM_last = newSAM_Node(0);
     43     SAM_node[0].pos = 0;
     44 }
     45 
     46 void SAM_add(int x, int len){
     47     SAM_Node *p = SAM_last, *np = newSAM_Node(p->len + 1);
     48     np->pos = len;
     49     SAM_last = np;
     50     for(; p && !p->next[x]; p = p->fa) p->next[x] = np;
     51     if(!p){
     52         np->fa = SAM_root;
     53         return;
     54     }
     55     SAM_Node *q = p->next[x];
     56     if(q->len == p->len + 1){
     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) p->next[x] = nq;
     65 }
     66 
     67 void SAM_build(char *s){
     68     SAM_init();
     69     int len = strlen(s);
     70     for(int i = 0; i < len; i++){
     71         SAM_add(s[i] - 'a', i + 1);
     72     }
     73 }
     74 
     75 int Q[MAXN][MAXN];
     76 char str[MAXN];
     77 
     78 int main(void){
     79     int t;
     80     scanf("%d", &t);
     81     while(t--){
     82         scanf("%s", str);
     83         memset(Q, 0, sizeof(Q));
     84         int n = strlen(str);
     85         for(int i = 0; i < n; i++){
     86             SAM_init();
     87             for(int j = i; j < n; j++){
     88                 SAM_add(str[j] - 'a', j - i + 1);
     89             }
     90             for(int j = 1; j < SAM_size; j++){
     91                 Q[i][SAM_node[j].pos + i - 1] += SAM_node[j].len - SAM_node[j].fa->len;
     92             }
     93             for(int j = i + 1; j < n; j++){
     94                 Q[i][j] += Q[i][j - 1];
     95             }
     96         }
     97         int q, l, r;
     98         scanf("%d", &q);
     99         while(q--){
    100             scanf("%d%d", &l, &r);
    101             printf("%d
    ", Q[l - 1][r - 1]);
    102         }
    103     }
    104     return 0;
    105 }
    View Code
  • 相关阅读:
    调试
    node笔记汇总
    移动端布局
    css 易错点总结
    Angular笔记
    CANVAS笔记
    http笔记汇总
    各种环境搭建 软件安装等等 参考网址收录
    js中同步异步,任务队列
    node.js之fs模块
  • 原文地址:https://www.cnblogs.com/geloutingyu/p/7474267.html
Copyright © 2011-2022 走看看