• hihoCoder #1445 : 后缀自动机二·重复旋律5


    #1445 : 后缀自动机二·重复旋律5

    时间限制:10000ms
    单点时限:2000ms
    内存限制:256MB

    描述

    小Hi平时的一大兴趣爱好就是演奏钢琴。我们知道一个音乐旋律被表示为一段数构成的数列。

    现在小Hi想知道一部作品中出现了多少不同的旋律?

    解题方法提示

    输入

    共一行,包含一个由小写字母构成的字符串。字符串长度不超过 1000000。

    输出

    一行一个整数,表示答案。

    样例输入
    aab
    样例输出
    5

    后缀自动机,学习了最短路的转移。

     1 /*************************************************************************
     2     > File: main.cpp
     3     > Author: You Siki
     4     > Mail: You.Siki@outlook.com 
     5     > Time: 2016年12月23日 星期五 14时25分55秒
     6  ************************************************************************/
     7 
     8 #include<bits/stdc++.h>
     9 
    10 //using namespace std;
    11 
    12 const int maxn = 2000005;
    13 
    14 /* AUTOMATON */
    15 
    16 int last = 1;
    17 int tail = 2;
    18 int step[maxn];
    19 int fail[maxn];
    20 int mini[maxn];
    21 int next[maxn][26];
    22 
    23 inline void buildAutomaton(char *s)
    24 {
    25     while (*s)
    26     {
    27         int p = last;
    28         int t = tail++;
    29         int c = *s++ - 'a';
    30         step[t] = step[p] + 1;
    31         while (p && !next[p][c])
    32             next[p][c] = t, p = fail[p];
    33         if (p)
    34         {
    35             int q = next[p][c];
    36             if (step[q] == step[p] + 1)
    37                 fail[t] = q, mini[t] = step[q] + 1;
    38             else
    39             {
    40                 int k = tail++;
    41                 fail[k] = fail[q];
    42                 fail[q] = fail[t] = k;
    43                 step[k] = step[p] + 1;
    44                 mini[q] = step[k] + 1;
    45                 mini[t] = step[k] + 1;
    46                 for (int i = 0; i < 26; ++i)
    47                     next[k][i] = next[q][i];
    48                 while (p && next[p][c] == q)
    49                     next[p][c] = k, p = fail[p];
    50                 mini[k] = step[fail[k]] + 1;
    51             }
    52         }
    53         else
    54             fail[t] = 1, mini[t] = 1;
    55         last = t;
    56     }
    57 }
    58 
    59 inline long long solve(void)
    60 {
    61     long long ret = 0;
    62     for (int i = 2; i < tail; ++i)
    63         ret += step[i] - mini[i] + 1;
    64     return ret;
    65 }
    66 
    67 /* MAIN FUNC */
    68 
    69 char str[maxn];
    70 
    71 signed main(void)
    72 {
    73     scanf("%s", str);
    74     buildAutomaton(str);
    75     printf("%lld
    ", solve());
    76 }

    20170222 复习SAM模板

     1 #include <cstdio>
     2 #include <cstring>
     3 
     4 const int siz = 2000005;
     5 
     6 int last = 1;
     7 int tail = 2;
     8 int mini[siz];
     9 int maxi[siz];
    10 int fail[siz];
    11 int next[siz][26];
    12 
    13 inline void build(char *s)
    14 {
    15     while (*s)
    16     {
    17         int p = last;
    18         int t = tail++;
    19         int c = *s++ - 'a';
    20 
    21         maxi[t] = maxi[p] + 1;
    22 
    23         while (p && !next[p][c])
    24             next[p][c] = t, p = fail[p];
    25         
    26         if (p)
    27         {
    28             int q = next[p][c];
    29 
    30             if (maxi[q] == maxi[p] + 1)
    31                 fail[t] = q, mini[t] = maxi[q] + 1;
    32             else
    33             {
    34                 int k = tail++;
    35 
    36                 fail[k] = fail[q];
    37                 fail[t] = fail[q] = k;
    38                 maxi[k] = maxi[p] + 1;
    39                 mini[q] = maxi[k] + 1;
    40                 mini[t] = maxi[k] + 1;
    41                 mini[k] = maxi[fail[k]] + 1;
    42 
    43                 memcpy(next[k], next[q], 26 * sizeof(int));
    44                 
    45                 while (next[p][c] == q)
    46                     next[p][c] = k, p = fail[p];
    47             }
    48         }
    49         else
    50             fail[t] = 1, mini[t] = 1;
    51 
    52         last = t;
    53     }
    54 }
    55 
    56 inline void calc(void)
    57 {
    58     long long ans = 0;
    59 
    60     for (int i = 2; i < tail; ++i)
    61         ans += maxi[i] - mini[i] + 1;
    62 
    63     printf("%lld
    ", ans);
    64 }
    65 
    66 signed main(void)
    67 {
    68     static char s[siz];
    69 
    70     scanf("%s", s);
    71 
    72     build(s);
    73 
    74     calc();
    75 }
    View Code

    @Author: YouSiki

  • 相关阅读:
    Oracle查询一个用户的所有表的结构信息的SQL语句
    Unable to locate provider for protocol: smtp
    IE6 IE7 IE8(Q) 不支持 JSON 对象
    如何获取tinyeditor编辑器里面的值
    POJ 2513 Colored Sticks 字典树 + 并查集 + 欧拉路
    HDOJ 2574 Hdu Girls' Day
    HDOJ 2087 剪花布条 KMP算法
    HDOJ 2094 产生冠军
    NYOJ525 一道水题
    POJ 2406 power strings KMP中next函数的应用
  • 原文地址:https://www.cnblogs.com/yousiki/p/6214870.html
Copyright © 2020-2023  润新知