dyllalala

导航

[hdu 4622]Reincarnation

这道题是妥妥的后缀自动机裸题

学了后缀自动机后,我居然感觉这尼玛果然还是后缀数组最难了有木有!

后缀自动机我的理解就是一个动态的存后缀的 AC 自动机

以为后缀的特殊性,我们可以在上一次插入的节点后直接插入新的节点,然后沿着 fail(pre) 指针把一些该更新的更新掉即可

果然是好写好用喵~

 

如何统计 [i..j] 的不同子串数呢?我们注意到每个节点 step 就是根到该节点的最长路径的长度

也就是以该节点结尾的后缀的最长长度

p->step-p->fail->step 就是节点 p 被插入后缀自动机后新增的以 p 为结尾的子串数量

这样一来题目就没有任何压力了有不有喵~

 

  1 #include <cstdio>
  2 #include <cstring>
  3 const int sizeOfString=2048;
  4 const int sizeOfMemory=1000000;
  5 const int sizeOfType=26;
  6 
  7 namespace IOspace
  8 {
  9     inline int getint()
 10     {
 11         register int num=0;
 12         register char ch;
 13         do ch=getchar(); while (ch<'0' || ch>'9');
 14         do num=num*10+ch-'0', ch=getchar(); while (ch>='0' && ch<='9');
 15         return num;
 16     }
 17     inline void putint(int num, char ch='\n')
 18     {
 19         char stack[10];
 20         register int top=0;
 21         for ( ;num;num/=10) stack[++top]=num%10+'0';
 22         for ( ;top;top--) putchar(stack[top]);
 23         if (ch) putchar(ch);
 24     }
 25 }
 26 namespace suffixAutomaton
 27 {
 28     struct node
 29     {
 30         int step;
 31         node * pre;
 32         node * ch[sizeOfType];
 33         inline int calc() {return pre?step-pre->step:0;}
 34     };
 35     int tot=0;
 36     node memory[sizeOfMemory], * port;
 37     node * dfa, * last;
 38     inline node * newnode(node * t)
 39     {
 40         node * newt=port++;
 41         newt->step=0;
 42         if (t) newt->pre=t->pre, t->pre=newt, memcpy(newt->ch, t->ch, sizeof t->ch);
 43         else newt->pre=NULL, memset(newt->ch, 0, sizeof newt->ch);
 44         return newt;
 45     }
 46     inline void clear() {tot=0; port=memory; dfa=newnode(NULL); dfa->pre=dfa; last=dfa;}
 47 
 48     inline int ord(char ch) {return ch-'a';}
 49     inline void insert(int w)
 50     {
 51         node * p=last, * newp=newnode(NULL);
 52         newp->step=p->step+1;
 53 
 54         for ( ;p->ch[w]==NULL;p=p->pre) p->ch[w]=newp;
 55         if (p->ch[w]==newp)
 56             newp->pre=dfa, tot+=newp->calc();
 57         else
 58         {
 59             node * q=p->ch[w];
 60             if (p->step+1==q->step)
 61                 newp->pre=q, tot+=newp->calc();
 62             else
 63             {
 64                 tot-=p->calc()+q->calc();
 65                 node * newq=newnode(q);
 66                 newq->step=p->step+1;
 67                 newp->pre=newq;
 68                 tot+=p->calc()+q->calc()+newp->calc()+newq->calc();
 69                 for ( ;p->ch[w]==q;p=p->pre) p->ch[w]=newq;
 70             }
 71         }
 72 
 73         last=newp;
 74     }
 75 }
 76 
 77 int T, n;
 78 char s[sizeOfString];
 79 int ans[sizeOfString][sizeOfString];
 80 
 81 int main()
 82 {
 83     for (T=IOspace::getint();T;T--)
 84     {
 85         scanf("%s", s);
 86         int len=strlen(s);
 87         memset(ans, 0, sizeof ans);
 88         for (int i=0;i<len;i++)
 89         {
 90             suffixAutomaton::clear();
 91             for (int j=i;j<len;j++)
 92             {
 93                 suffixAutomaton::insert(suffixAutomaton::ord(s[j]));
 94                 ans[i][j]=suffixAutomaton::tot;
 95             }
 96         }
 97         n=IOspace::getint();
 98         for (int i=1;i<=n;i++)
 99         {
100             int l=IOspace::getint()-1, r=IOspace::getint()-1;
101             IOspace::putint(ans[l][r]);
102         }
103     }
104 
105     return 0;
106 }
本傻装B系列

 

posted on 2014-08-14 17:54  dyllalala  阅读(226)  评论(0编辑  收藏  举报