• SPOJ 8222 Substrings (后缀自动机)


    转载:http://hzwer.com/4420.html

    给一个字符串S,令F(x)表示S的所有长度为x的子串中,出现次数的最大值。

    求F(1)..F(Length(S)) Length(S) <= 250000

    我们构造S的后缀自动机(SAM),那么对于一个节点s,它的长度范围是 [Min(s),Max(s)],同时他的出现次数是|Right(s)|。

    那么我们用 |Right(s)|去更新F(Max(s))的值。 同时最后从大到小依次用F(i)去更新F(i-1)即可。

    对于SAM,我口胡几句吧

    自动机每个结点信息是一个right集合

    比如串aaabbaaabd

    aaab在其中1-4 6-9出现

    则自动机在读入aaab到达的结点是{4,9}

    aab和ab也应该到达这个结点,因为他们出现的结尾也是{4,9}

    而b是{4,5,9}不到达这个结点

    显然,对于一个状态s,若长度l<=r所对应的al,ar满足

    ST(al)=ST(ar)=s那么对于任意的l<=x<=r,ST(ax)=s

    不妨设s所有合法集合为[Min(s),Max(s)]

    al指的是串a的前l个

    显然节点信息是集合包含关系

    随着串长增加就是集合元素减少

    构建自动机的目标就是让所有包含关系变为一棵树

    构建实际上很简单。。。

      1 1
      2 2
      3 3
      4 4
      5 5
      6 6
      7 7
      8 8
      9 9
     10 10
     11 11
     12 12
     13 13
     14 14
     15 15
     16 16
     17 17
     18 18
     19 19
     20 20
     21 21
     22 22
     23 23
     24 24
     25 25
     26 26
     27 27
     28 28
     29 29
     30 30
     31 31
     32 32
     33 33
     34 34
     35 35
     36 36
     37 37
     38 38
     39 39
     40 40
     41 41
     42 42
     43 43
     44 44
     45 45
     46 46
     47 47
     48 48
     49 49
     50 50
     51 51
     52 52
     53 53
     54 #include<iostream>
     55 #include<cstdio>
     56 #include<cstring>
     57 #include<cstdlib>
     58 #include<algorithm>
     59 #include<cmath>
     60 #define N 500005
     61 #define ll long long
     62 using namespace std;
     63 char s[N];
     64 int S,cnt,last;
     65 int a[N],b[N],f[N],t[N],fa[N],l[N],r[N],ch[N][26];
     66 void add(int x)
     67 {
     68     int c=a[x];
     69     int p=last,np=++cnt;last=np;
     70     l[np]=x;
     71     for(;p&&!ch[p][c];p=fa[p])ch[p][c]=np;
     72     if(!p)fa[np]=S;
     73     else 
     74     {
     75         int q=ch[p][c];
     76         if(l[p]+1==l[q])fa[np]=q;
     77         else 
     78         {
     79             int nq=++cnt;l[nq]=l[p]+1;
     80             memcpy(ch[nq],ch[q],sizeof ch[q]);
     81             fa[nq]=fa[q];
     82             fa[np]=fa[q]=nq;
     83             for(;ch[p][c]==q;p=fa[p])ch[p][c]=nq;
     84         }
     85     }
     86 }
     87 int main()
     88 {
     89     scanf("%s",s+1);
     90     last=S=++cnt;
     91     int len=strlen(s+1);
     92     for(int i=1;i<=len;i++)a[i]=s[i]-'a';
     93     for(int i=1;i<=len;i++)add(i);
     94     for(int i=1,p=S;i<=len;i++)
     95     {
     96         p=ch[p][a[i]];r[p]++;
     97     }
     98     for(int i=1;i<=cnt;i++)b[l[i]]++;
     99     for(int i=1;i<=len;i++)b[i]+=b[i-1];
    100     for(int i=1;i<=cnt;i++)t[b[l[i]]--]=i;
    101     for(int i=cnt;i;i--)r[fa[t[i]]]+=r[t[i]];
    102     for(int i=1;i<=cnt;i++)f[l[i]]=max(f[l[i]],r[i]);
    103     for(int i=len;i;i--)f[i]=max(f[i+1],f[i]);
    104     for(int i=1;i<=len;i++)printf("%d
    ",f[i]);
    105     return 0;
    106 }
  • 相关阅读:
    windows7通过Dns.GetHostAddresses(Dns.GetHostName())获得ipv6地址转换到ipv4
    题解 P3829 【[SHOI2012]信用卡凸包】
    点积与叉积
    点分治
    珂朵莉树
    NOIP2020模拟赛(二十五)7.26 结题报告
    树连剖分
    NOIP2020模拟赛(拾)解题报告
    题解 P2538 【[SCOI2008]城堡】
    模拟退火
  • 原文地址:https://www.cnblogs.com/agenthtb/p/7696169.html
Copyright © 2020-2023  润新知