zoukankan      html  css  js  c++  java
  • gym101431B

    以此纪念我都快忘了的后缀自动机(捂脸)

    不过这题有两种做法:

    用后缀自动机,先把原串再接遍中间加入特殊连接字符再把原串反接两遍,对这个新构造出的串做后缀自动机。(或者直接建立广义后缀自动机)

    下面只要统计长度小于等于 n 的串即可。这可以从 parent 树即后缀树来考虑,注意到每个节点可以接收的子串长度为[mxlen[fa[x]]+1,mxlen[x]]

    只要对这个长度区间对n取min再统计即可

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 typedef long long ll;
     5 int fa[400010],go[400010][26],mx[400010],n,t,last;
     6 char a[50010];
     7 void add(int c)
     8 {
     9     int np,nq,q,p=last;
    10     if (!go[last][c])
    11     {
    12         np=++t;
    13         mx[np]=mx[p]+1;
    14         for (;p&&!go[p][c]; p=fa[p]) go[p][c]=np;
    15     }
    16     else np=0;
    17     if (!p) fa[np]=1;
    18     else {
    19         q=go[p][c];
    20         if (mx[q]==mx[p]+1) fa[np]=q;
    21         else {
    22             nq=++t;
    23             mx[nq]=mx[p]+1;
    24             memcpy(go[nq],go[q],sizeof(go[q]));
    25             fa[nq]=fa[q]; fa[q]=fa[np]=nq;
    26             for (;go[p][c]==q; p=fa[p]) go[p][c]=nq;
    27         }
    28     }
    29     last=go[last][c];
    30 }
    31 
    32 int main()
    33 {
    34     scanf("%d",&n);
    35     scanf("%s",a+1);
    36     last=t=1;
    37     for (int i=1; i<=n; i++)
    38         add(a[i]-'a');
    39     for (int i=1; i<=n; i++)
    40         add(a[i]-'a');
    41     last=1;
    42     for (int i=n; i; i--)
    43         add(a[i]-'a');
    44     for (int i=n; i; i--)
    45         add(a[i]-'a');
    46     ll ans=0;
    47     for (int i=2; i<=t; i++)
    48         ans+=min(n,mx[i])-min(mx[fa[i]],n);
    49     printf("%lld
    ",ans);
    50 }
    自动机

    另一种诡异的做法:由于数据随机,那么当串长足够大时很大概率都是互不相同的,干脆就直接认为全不相同

    因此只要找小串长的不同种类即可,这就直接用 hash

    暴力判断即可。

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 typedef long long ll;
     5 char a[50010];
     6 set<ll> f[20];
     7 int n;
     8 using namespace std;
     9 typedef long long ll;
    10 const int mx=15;
    11 int main()
    12 {
    13     scanf("%d",&n);
    14     scanf("%s",a);
    15     for (int i=0; i<n; i++)
    16     {
    17         ll h1=0,h2=0;
    18         for (int l=0; l<min(n,mx); l++)
    19         {
    20             h1=h1*26+a[(i+l)%n]-'a';
    21             h2=h2*26+a[(i-l+n)%n]-'a';
    22             f[l].insert(h1);
    23             f[l].insert(h2);
    24         }
    25     }
    26     ll ans=2ll*n*max(0,n-mx);
    27     for (int l=0; l<mx; l++)
    28         ans+=f[l].size();
    29     printf("%lld
    ",ans);
    30 }
    View Code
  • 相关阅读:
    MyBatis高级查询 存储过程
    MyBatis高级查询 一对多映射
    第20章-使用JMX管理Spring Bean
    第19章-使用Spring发送Email
    第18章-使用WebSocket和STOMP实现消息功能
    第17章-Spring消息
    第16章-使用Spring MVC创建REST API
    第15章-使用远程服务
    基于IKAnalyzer搭建分词服务
    第08章-使用Spring Web Flow
  • 原文地址:https://www.cnblogs.com/phile/p/7206608.html
Copyright © 2011-2022 走看看