hihocoder1445 后缀自动机二·重复旋律5
传送门:http://hihocoder.com/problemset/problem/1445
【题解】
大概看了一天的后缀自动机,总算懂了一些
这篇文章写的非常好,诚意安利:Suffix Automaton Tutorial - Hunt Zhan
我就是看了这个大概懂了。
整个过程大概是:每次插入一个state可能会分裂原有的state的transition,就维护这个transition即可。
要用par[x]记录suffix-link是谁。
过程中可以不用记录minlen,因为$minlen[i] = maxlen[par[i]] + 1$,这点非常重要。
这题前面写了后缀自动机,然后上面像统计子树一样统计,后来发现,复杂度是$O(n * 26)$,似乎太大了,TLE了。
其实后缀自动机的每个state都含有若干子串,所有state的含有子串个数之和就是总个数了。
每个state含有子串个数为$maxlen[i] - minlen[i]$,这里把$minlen[i]$替换成$maxlen[par[i]] + 1$即可,不需要再求$minlen[i]$。
这样复杂度就差不多$O(n)$了,常数小了。
# include <stdio.h>
# include <string.h>
# include <iostream>
# include <algorithm>
// # include <bits/stdc++.h> using namespace std; typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int N = 1e6 + , M = 2e6 + ;
const int mod = 1e9+; char str[N];
struct SAM {
int ch[M][], par[M], ml[M];
int siz, rt, last;
inline void set() {
siz = rt = last = ;
memset(ch, , sizeof ch);
memset(par, , sizeof par);
memset(ml, , sizeof ml);
}
inline void extend(int c) {
int p = last, cur = ++siz;
ml[cur] = ml[p] + ;
for (; p && !ch[p][c]; p = par[p]) ch[p][c] = cur;
if(!p) par[cur] = rt;
else {
int q = ch[p][c];
if(ml[q] == ml[p] + ) par[cur] = q;
else {
int sq = ++siz;
par[sq] = par[q];
for (int i=; i<; ++i) ch[sq][i] = ch[q][i];
ml[sq] = ml[p] + ;
par[q] = par[cur] = sq;
for (; p && ch[p][c] == q; p = par[p]) ch[p][c] = sq;
}
}
last = cur;
}
}S; /*
ll f[M];
inline void dfs(int x) {
f[x] = 1;
for (int i=0; i<26; ++i) {
if(!S.ch[x][i]) continue;
dfs(S.ch[x][i]);
f[x] += f[S.ch[x][i]];
}
}
*/ int main() {
scanf("%s", str+); S.set();
for (int i=; str[i]; ++i) S.extend(str[i] - 'a');
ll ans = ;
for (int i=; i<=S.siz; ++i) {
if(i == S.rt) continue;
ans += S.ml[i] - S.ml[S.par[i]];
}
cout << ans;
return ;
}
hihocoder1445 后缀自动机二·重复旋律5的更多相关文章
- 【后缀自动机】hihocoder1445 后缀自动机二·重复旋律5
解题方法提示 小Hi:本周的题目其实就是给定一个字符串S,要求出S的所有不同子串的数目.小Ho你知道如何快速求解么? 小Ho:我们最近在讨论后缀自动机,所以肯定是和后缀自动机有关!根据上周学习的SAM ...
- HihoCoder1445 后缀自动机二·重复旋律5(后缀自动机 子串种数)
题意: 询问串的不同子串个数 思路: 后缀自动机每个节点表示以当前字符结尾的一系列后缀,个数为\(maxlen - minlen\),其中\(minlen = maxlen[father]\). 代码 ...
- hihoCoder #1445 : 后缀自动机二·重复旋律5
#1445 : 后缀自动机二·重复旋律5 时间限制:10000ms 单点时限:2000ms 内存限制:256MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一个音乐旋律被表示为一段数构成的数 ...
- hihoCoder_1445_后缀自动机二·重复旋律5
#1445 : 后缀自动机二·重复旋律5 时间限制:10000ms 单点时限:2000ms 内存限制:512MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一个音乐旋律被表示为一段数构成的数 ...
- hiho一下第128周 后缀自动机二·重复旋律5
#1445 : 后缀自动机二·重复旋律5 时间限制:10000ms 单点时限:2000ms 内存限制:512MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一个音乐旋律被表示为一段数构成的数 ...
- hiho一下第131周 后缀自动机二·重复旋律8(循环相似子串)
后缀自动机五·重复旋律8 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一段音乐旋律可以被表示为一段数构成的数列. 小Hi ...
- hiho一下第130周 后缀自动机二·重复旋律7
后缀自动机四·重复旋律7 时间限制:15000ms 单点时限:3000ms 内存限制:512MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一段音乐旋律可以被表示为一段数构成的数列. 神奇的 ...
- hiho一下第129周 后缀自动机二·重复旋律6
后缀自动机三·重复旋律6 时间限制:15000ms 单点时限:3000ms 内存限制:512MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一个音乐旋律被表示为一段数构成的数列. 现在小Hi ...
- hihocoder 后缀自动机二·重复旋律5
求不同子串个数 裸的后缀自动机 #include<cstring> #include<cmath> #include<iostream> #include<a ...
随机推荐
- 求gcd(最大公因数),lcm(最小公倍数)模板
gcd(最大公因数),lcm(最小公倍数) #include<iostream> using namespace std; int gcd(int a,int b)//辗转相除法(欧几里德 ...
- jsp连接MYSQL数据库教程(文字+图)
步骤: 1.在mysql官网下载JDBC驱动程序.网址:https://dev.mysql.com/downloads/connector/j/ 2.把里面的jar包(mysql-connector- ...
- 【转】关于增量链接(incremental linking)
增量链接(Incremental Linking)这个词语在使用Visual C++时经常会遇到(其实不只是VS系列,其它链接器也有这个特性), 就比如经常遇到的:上一个增量链接没有生成它, 正在执行 ...
- JQuery 学习笔记--02
JS 中的 window.onload() 方法与 Jquery 中的 $(document).read(function( ){ }) 的区别 : 加载时机不一样, window.onload() ...
- 小程序出现 “2 not found” 解决方案
今天新建小程序的时候出现 ,控制台出现“2 not found” 报错. 解决方法: 在控制台输入 openVendor() , 然后会弹出开发工具的文件夹,删除掉下图这两个程序,重启开发工具就可 ...
- 【bzoj1614】[Usaco2007 Jan]Telephone Lines架设电话线 二分+SPFA
题目描述 Farmer John打算将电话线引到自己的农场,但电信公司并不打算为他提供免费服务.于是,FJ必须为此向电信公司支付一定的费用. FJ的农场周围分布着N(1 <= N <= 1 ...
- BZOJ4000 TJOI2015棋盘(状压dp+矩阵快速幂)
显然每一行棋子的某种放法是否合法只与上一行有关,状压起来即可.然后n稍微有点大,矩阵快速幂即可. #include<iostream> #include<cstdio> #in ...
- Elasticsearch 中文分词器IK
1.安装说明 https://github.com/medcl/elasticsearch-analysis-ik 2.release版本 https://github.com/medcl/elast ...
- [AHOI2009]中国象棋 DP,递推,组合数
DP,递推,组合数 其实相当于就是一个递推推式子,然后要用到一点组合数的知识 一道很妙的题,因为不能互相攻击,所以任意行列不能有超过两个炮 首先令f[i][j][k]代表前i行,有j列为一个炮,有k列 ...
- Android 使用LocationManger进行定位
在Android应用中,往往有获取当前地理位置的需求,比如微信获取附近的人需要获取用户当前的位置,不多说,直接上例子. public Location getLocation() { Location ...