zoukankan      html  css  js  c++  java
  • 【spoj8222】Substrings

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cmath>
     5 #include <algorithm>
     6 #define maxn 500005
     7 #define maxm 250005
     8 using namespace std;
     9 
    10 int n,tot,root,last,f[maxm],fa[maxn],son[maxn][26],dist[maxn],ri[maxn],sum[maxm],tmp[maxn];
    11 char st[maxm];
    12 struct Tsegment{
    13     void prepare(){tot=root=last=1; memset(dist,0,sizeof(dist)); memset(sum,0,sizeof(sum));}
    14     int newnode(int x){
    15         dist[++tot]=x; return tot;
    16     }
    17     void add(int x){
    18         int p=last,np=newnode(dist[last]+1); last=np;
    19         for (;p&&!son[p][x];p=fa[p]) son[p][x]=np;
    20         if (p==0) fa[np]=root;
    21         else{
    22             int q=son[p][x];
    23             if (dist[p]+1==dist[q]) fa[np]=q;
    24             else{
    25                 int nq=newnode(dist[p]+1);
    26                 memcpy(son[nq],son[q],sizeof(son[q]));
    27                 fa[nq]=fa[q],fa[q]=fa[np]=nq;
    28                 for (;p&&son[p][x]==q;p=fa[p]) son[p][x]=nq;
    29             }
    30         } 
    31     }
    32 }SAM;
    33 
    34 int main(){
    35     scanf("%s",st+1),n=strlen(st+1);
    36     SAM.prepare();
    37     for (int i=1;i<=n;i++) SAM.add(st[i]-'a');
    38     last=root;
    39     for (int i=1;i<=n;i++) last=son[last][st[i]-'a'],ri[last]=1;
    40     memset(sum,0,sizeof(sum));
    41     for (int i=1;i<=tot;i++) sum[dist[i]]++;
    42     for (int i=1;i<=n;i++) sum[i]+=sum[i-1];
    43     for (int i=1;i<=tot;i++) tmp[sum[dist[i]]--]=i;
    44     memset(f,0,sizeof(f));
    45     for (int i=tot;i>=1;i--){
    46         int x=tmp[i];
    47         if (fa[x]) ri[fa[x]]+=ri[x];
    48     }
    49     for (int i=1;i<=tot;i++) f[dist[i]]=max(f[dist[i]],ri[i]);
    50     for (int i=n-1;i>=1;i--) f[i]=max(f[i],f[i+1]);
    51     for (int i=1;i<=n;i++) printf("%d
    ",f[i]);
    52     return 0;
    53 }
    View Code

    题目链接:http://www.spoj.com/problems/NSUBSTR/

    题目大意:给定一个长度为n的字符串,n<=250000,求f[i],i属于[1,n],f[i]表示在给定字符串中长度为i的子串的最多出现次数。

    做法:初看此题,我也是一脸懵逼,后来发现出现次数与后缀自动机中的right集合大小有关,这题主要就是如何求right集合的大小,即该点表示的状态的右端点的个数(即出现次数),初始时我们从root开始匹配全串,途径的节点我们设其right为1,其余的节点设为0,某个节点的right就是parent树中以它为根的子树中的right值的和,一次dp即可。注解:parent树是我们记录的fa数组所构成的树,该步骤具体细节见代码。

    dist表示SAM上该节点所表示的状态所能代表的最长的字符串长度,我们用right【i】去更新f【dist【i】】即可,最后用一次类似前缀和的算法,求一次后缀最值,显然,长度越小,出现次数一定不会减少。最后输出f数组即可。

    后缀自动机。

  • 相关阅读:
    从零开始搭建高性能高可用Tomcat服务器
    Tomcat性能优化
    Centos配置ARP和Tomcat Native
    使用idea2017搭建SSM框架
    js/java常用正则表达式及写法
    悬浮提示工具(悬浮出现自动消失)
    input和div模仿select,带输入提示
    使用js函数格式化xml字符串带缩进
    我的前端工具集(十)按钮点击操作锁
    我的前端工具集(九)树工具重新封装和修改
  • 原文地址:https://www.cnblogs.com/OYzx/p/5549730.html
Copyright © 2011-2022 走看看