[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系列

 

你可能感兴趣的:(HDU)