• Luogu P4070 [SDOI2016]生成魔咒


    题意:求本质不同的子串数。

    (SA)

    (SAM+DP)

    答案即为路径条数。

    我们设 (f[u]) 表示从 (u) 出发的路径条数:(f[u]=1+sum_{(u,v,ch)} f[v]) ,其中 (1) 代表空串。

    最后答案即为 (f[0]-1)

    (SAM+parent树)

    每个子串只会出现一次,并且每个点的 (sz) 即为 (maxlen[u]-minlen[u])

    答案为 (sum len[u]-len[fa[u]])

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<unordered_map>
    #define R register int
    #define ll long long
    using namespace std;
    namespace Luitaryi {
    inline int g() { R x=0,f=1;
      register char s; while(!isdigit(s=getchar())) f=s=='-'?-1:f;
      do x=x*10+(s^48); while(isdigit(s=getchar())); return x*f;
    } 
    const int N=100010;
    int n,tot=1,lst=1;
    int fa[N],len[N];
    ll ans;
    unordered_map<int,int> c[N];
    inline void add(int ch) {
      R p=lst,np=lst=++tot;
      len[np]=len[p]+1;
      for(;p&&!c[p].count(ch);p=fa[p]) c[p][ch]=np;
      if(!p) fa[np]=1;
      else {
        R q=c[p][ch];;
        if(len[q]==len[p]+1) fa[np]=q;
        else {
          R nq=++tot;
          c[nq]=c[q];
          fa[nq]=fa[q],len[nq]=len[p]+1;
          fa[q]=fa[np]=nq;
          for(;p&&c[p].count(ch)&&c[p][ch]==q;p=fa[p]) c[p][ch]=nq;
        }
      }
      printf("%lld
    ",ans+=len[np]-len[fa[np]]);
    }
    inline void main() {
      n=g();
      for(R i=1;i<=n;++i) add(g());
    }
    } signed main() {Luitaryi::main(); return 0;}
    

    2019.01.09

  • 相关阅读:
    Metropolis-Hastings algorithm
    Base64编码原理
    修改远程端口号
    修改数据库配置文件
    Windows 2008下系统网站运行环境的搭建
    oracle 11 g数据库卸载(方法二)
    oracle11g的安装
    oracle 11g的卸载
    软件实施的技巧
    使用命令行快速打开系统文件
  • 原文地址:https://www.cnblogs.com/Jackpei/p/12177391.html
Copyright © 2020-2023  润新知