• [hdu 4416]Good Article Good sentence


    最近几天一直在做有关后缀自动机的题目

    感觉似乎对后缀自动机越来越了解了呢!喵~

    这题还是让我受益颇多的,首先搞一个后缀自动机是妥妥的了

    可是搞完之后呢?

    我们来观察 step 这个变量,每个节点的 step 是从根节点到此节点所经过的最长步数

    那么也就是以该点为结尾的最长的后缀长度

    如何统计不被 Bi 串包含的子串呢?

    其实很简单,维护每个节点所能匹配的最长的字符串长度

    然后 节点->step-max(该节点所能匹配的最长的字符串长度, 节点->fail->step) 就是答案了

    因为 S[0..节点->step-1] 必是原串的一个后缀,而 节点所能匹配的最长字符串长度 d 说明 S[节点->step-d..节点->step-1] 是出现在了某个 Bi 串中的

    只不过把每个串在自动机上跑一遍并不能得到每个节点所能匹配的最长长度

    因为当该节点被匹配时,该结点的 fail 指针所指向的节点也必然被匹配到了

    我们需要一个拓扑排序,按拓扑序来更新答案,并同时更新每个节点的 fail 指针指向的点的匹配长度

    教练,我不想写拓扑排序~

    我才不会说按 step 从大到小的顺序就是拓扑序呢喵~

    namespace 写写被 hdu 怒骂 TLE TAT ,这是多么痛的领悟……

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <algorithm>
      4 #define ord(ch) ((ch)-'a')
      5 typedef long long llint;
      6 const int sizeOfString=550005;
      7 const int sizeOfMemory=550005<<1;
      8 const int sizeOfType=26;
      9 
     10 inline int max(int x, int y) {return x>y?x:y;}
     11 
     12 struct node
     13 {
     14     int step;
     15     int same;
     16     node * fail;
     17     node * ch[sizeOfType];
     18 };
     19 node memory[sizeOfMemory]; int port;
     20 node * dfa=memory, * last;
     21 inline node * newnode(node * t=NULL)
     22 {
     23     node * newt=memory+(port++);
     24     newt->step=0;
     25     newt->same=0;
     26     if (t) newt->fail=t->fail, t->fail=newt, memcpy(newt->ch, t->ch, sizeof t->ch);
     27     else newt->fail=NULL, memset(newt->ch, 0, sizeof newt->ch);
     28     return newt;
     29 }
     30 inline void insert(int w)
     31 {
     32     node * p=last, * newp=newnode();
     33     newp->step=p->step+1;
     34 
     35     for ( ;p->ch[w]==NULL;p=p->fail) p->ch[w]=newp;
     36     if (p->ch[w]==newp)
     37         newp->fail=dfa;
     38     else
     39     {
     40         node * q=p->ch[w];
     41         if (q->step==p->step+1)
     42             newp->fail=q;
     43         else
     44         {
     45             node * newq=newnode(q);
     46             newq->step=p->step+1;
     47             newp->fail=newq;
     48             for ( ;p->ch[w]==q;p=p->fail) p->ch[w]=newq;
     49         }
     50     }
     51 
     52     last=newp;
     53 }
     54 inline void search(char * s)
     55 {
     56     int len=strlen(s);
     57     int tot=0;
     58     node * t=dfa;
     59     for (int i=0;i<len;i++)
     60     {
     61         int w=ord(s[i]);
     62         if (t->ch[w])
     63         {
     64             t=t->ch[w];
     65             t->same=max(t->same, ++tot);
     66         }
     67         else
     68         {
     69             node * j;
     70             for (j=t->fail;j!=dfa && !j->ch[w];j=j->fail);
     71             if (j->ch[w])
     72             {
     73                 t=j->ch[w];
     74                 t->same=max(t->same, tot=(j->step+1));
     75             }
     76             else
     77             {
     78                 t=dfa;
     79                 tot=0;
     80             }
     81         }
     82     }
     83 }
     84 inline llint calc(int len)
     85 {
     86     static node * p[sizeOfMemory];
     87     static int cnt[sizeOfString];
     88     llint ret=0;
     89 
     90     memset(cnt, 0, sizeof(cnt));
     91     for (int i=0;i<port;i++) cnt[dfa[i].step]++;
     92     for (int i=1;i<=len;i++) cnt[i]+=cnt[i-1];
     93     for (int i=0;i<port;i++) p[--cnt[dfa[i].step]]=&dfa[i];
     94     for (int i=port-1;i>0;i--)
     95     {
     96         p[i]->fail->same=max(p[i]->fail->same, p[i]->same);
     97         if (p[i]->same<p[i]->step)
     98             ret+=p[i]->step-max(p[i]->same, p[i]->fail->step);
     99     }
    100 
    101     return ret;
    102 }
    103 
    104 int T, n;
    105 char str[sizeOfString], s[sizeOfString];
    106 
    107 int main()
    108 {
    109     int cases=0;
    110 
    111     for (scanf("%d", &T);T;T--)
    112     {
    113         scanf("%d", &n);
    114         scanf("%s", str);
    115         port=0; dfa=newnode(); dfa->fail=dfa; last=dfa;
    116         int len=strlen(str);
    117         for (int i=0;i<len;i++)
    118             insert(ord(str[i]));
    119         for (int i=1;i<=n;i++)
    120         {
    121             scanf("%s", s);
    122             search(s);
    123         }
    124         printf("Case %d: %I64d
    ", ++cases, calc(len));
    125     }
    126 
    127     return 0;
    128 }
    本傻装B不成反被艹系列
  • 相关阅读:
    web端
    vue 键盘事件keyup/keydoen
    APiCloud
    APiCloud
    对于HTML和XML的理解
    JS 的三种定义变量 var let const
    jQuery
    NodeJS 阻塞/非阻塞
    NodeJs REPL交互式解析器常用命令
    用NodeJS创建一个聊天服务器
  • 原文地址:https://www.cnblogs.com/dyllalala/p/3915541.html
Copyright © 2020-2023  润新知