Substrings SPOJ - NSUBSTR (后缀自动机)
Substrings
\]
题意
给出一个长度为 \(250000\) 的字符串,求出所有 \(x\) 的 \(F(x)\) 。
\(F(x)\) 含义为长度为 \(x\) 的子串出现的最多次数。
思路
先对给出的串构建后缀自动机,设 \(dp[i]\) 为后缀自动机上节点 \(i\) 包含的最长子串的出现的次数。那么对于主链的上的点,可以直接赋初始值 \(dp[i] = 1\),也就是从根节点直接走到当前节点。
对于任意节点 \(i\) ,\(i\) 中出现的子串必定也会在其 \(father\) 上出现,所以我们可以得到
dp[father] += dp[i]。
如此就可以计算出节点 \(i\) 的子串的出现次数,得到
anslen[node[i].len] = max(anslen[node[i].len], dp[i]);
现在求出的是对于每个节点上 \(maxlen\) 的 \(anslen\),对于 \(\left[minlen,maxlen-1\right]\) 范围内还没有求出来,所以我们还要在更新一遍。
因为长度更短的子串一定包括在长度更长的子串中,所以可以得到
anslen[i] = max(anslen[i], anslen[i+1]);
最后输出\(anslen\)就是题目的\(F(x)\)。
#include <map>
#include <set>
#include <list>
#include <ctime>
#include <cmath>
#include <stack>
#include <queue>
#include <cfloat>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define lowbit(x) x & (-x)
#define mes(a, b) memset(a, b, sizeof a)
#define fi first
#define se second
#define pii pair<int, int>
#define INOPEN freopen("in.txt", "r", stdin)
#define OUTOPEN freopen("out.txt", "w", stdout)
typedef unsigned long long int ull;
typedef long long int ll;
const int maxn = 3e5 + 10;
const int maxm = 1e5 + 10;
const ll mod = 1e9 + 7;
const ll INF = 1e18 + 100;
const int inf = 0x3f3f3f3f;
const double pi = acos(-1.0);
const double eps = 1e-8;
using namespace std;
int n, m;
int cas, tol, T;
struct SAM {
struct Node{
int next[27];
int len, fa;
void init() {
mes(next, 0);
len = fa = 0;
}
} node[maxn<<1];
vector<int> vv[maxn<<1];
int dp[maxn<<1], anslen[maxn];
int sz, last;
void init() {
sz = last = 1;
node[sz].init();
mes(dp, 0);
mes(anslen, 0);
}
void insert(int k) {
int p = last, np = last = ++sz;
node[np].init();
dp[np] = 1;
node[np].len = node[p].len+1;
for(; p&&!node[p].next[k]; p=node[p].fa)
node[p].next[k] = np;
if(p==0) {
node[np].fa = 1;
} else {
int q = node[p].next[k];
if(node[q].len == node[p].len + 1) {
node[np].fa = q;
} else {
int nq = ++sz;
node[nq] = node[q];
node[nq].len = node[p].len+1;
node[np].fa = node[q].fa = nq;
for(; p&&node[p].next[k]==q; p=node[p].fa)
node[p].next[k] = nq;
}
}
}
void dfs(int u) {
for(auto v : vv[u]) {
dfs(v);
dp[u] += dp[v];
}
anslen[node[u].len] = max(anslen[node[u].len], dp[u]);
}
void solve(int len) {
for(int i=1; i<=sz; i++) {
vv[i].clear();
}
for(int i=2; i<=sz; i++) {
vv[node[i].fa].push_back(i);
}
dfs(1);
for(int i=len-1; i>=1; i--) {
anslen[i] = max(anslen[i], anslen[i+1]);
}
for(int i=1; i<=len; i++) {
printf("%d\n", anslen[i]);
}
}
} sam;
char s[maxn];
int main() {
scanf("%s", s+1);
sam.init();
int len = strlen(s+1);
for(int i=1; i<=len; i++) {
sam.insert(s[i]-'a'+1);
}
sam.solve(len);
return 0;
}
Substrings SPOJ - NSUBSTR (后缀自动机)的更多相关文章
- SPOJ NSUBSTR (后缀自动机)
SPOJ NSUBSTR Problem : 给一个长度为n的字符串,要求分别输出长度为1~n的子串的最多出现次数. Solution :首先对字符串建立后缀自动机,在根据fail指针建立出后缀树,对 ...
- SPOJ - NSUBSTR 后缀自动机板子
SPOJ - NSUBSTR #include<bits/stdc++.h> #define LL long long #define fi first #define se second ...
- 长度为x的本质不同的串的出现次数 SPOJ - NSUBSTR 后缀自动机简单应用
题意: 长度为x的本质不同的串的出现次数 题解: 先处理出每一个节点所对应的子串出现的次数 然后取max就好了 #include <set> #include <map> #i ...
- Distinct Substrings(spoj694)(sam(后缀自动机)||sa(后缀数组))
Given a string, we need to find the total number of its distinct substrings. Input \(T-\) number of ...
- Spoj-DISUBSTR - Distinct Substrings~New Distinct Substrings SPOJ - SUBST1~(后缀数组求解子串个数)
Spoj-DISUBSTR - Distinct Substrings New Distinct Substrings SPOJ - SUBST1 我是根据kuangbin的后缀数组专题来的 这两题题 ...
- SPOJ LCS 后缀自动机
用后缀自动机求两个长串的最长公共子串,效果拔群.多样例的时候memset要去掉. 解题思路就是跟CLJ的一模一样啦. #pragma warning(disable:4996) #include< ...
- Substrings(SPOJ8222) (sam(后缀自动机))
You are given a string \(S\) which consists of 250000 lowercase latin letters at most. We define \(F ...
- SPOJ - LCS 后缀自动机入门
LCS - Longest Common Substring A string is finite sequence of characters over a non-empty finite set ...
- SPOJ LCS 后缀自动机找最大公共子串
这里用第一个字符串构建完成后缀自动机以后 不断用第二个字符串从左往右沿着后缀自动机往前走,如能找到,那么当前匹配配数加1 如果找不到,那么就不断沿着后缀树不断往前找到所能匹配到当前字符的最大长度,然后 ...
随机推荐
- 低版本的 eclipse 不支持 tomcat8.5 的解决方法
目录 低版本的eclipse 不支持 tomcat8.5,但是还想使用的方法 低版本的eclipse 不支持 tomcat8.5,但是还想使用的方法 1. 介绍: 我在使用 mars 版本的 ec ...
- gevent介绍(转)
原文:https://www.liaoxuefeng.com/wiki/897692888725344/966405998508320 Python通过yield提供了对协程的基本支持,但是不完全.而 ...
- 获取html 中的内容 将前台的数据获取到后台 用 jquery 生成一个 form表单 提交数据
使用js创建一个form表单 ,使用post上传到后台中 下面是代码.在获取html内容的时候使用了js节点来获取内容. parent:父节点.上一级的节点 siblings:兄弟节点.同一级别的节点 ...
- ASP.NET Core 2.0升级到3.0的变化和问题
前言 在.NET Core 2.0发布的时候,博主也趁热使用ASP.NET Core 2.0写了一个独立的博客网站,现如今恰逢.NET Core 3.0发布之际,于是将该网站进行了升级. 下面就记录升 ...
- Android 权限的一些细节
Android 权限的一些细节 1 哪些app属于system app?为了区分privilege app和system app,这里先说明system app是什么,避免之后的讨论概念混乱. 在Pa ...
- axios + vue导出excel文件
(使用到了elementUI框架) <template> <el-button type="primary" size="mini" @cli ...
- word,excel,ppt转pdf
第一步 需要下载jar包和jacob-1.14.3-x64.dll * <dependency> * <groupId>net.sf.jacob-project</gro ...
- Python - 实现矩阵转置
有个朋友提出了一个问题:手头上现在有一个二维列表,比如[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]],现在要把该二维列表变成为[[1, 4, 7, 10 ...
- 93.vue---在vue环境用webuploader分片上传插件遇到的超级bug(独家仅此一份)
本来我是想想用vue-simple-uploader (https://www.cnblogs.com/xiahj/p/vue-simple-uploader.html)的 但是公司后台已经做好了we ...
- MyCat教程四:实现读写分离
本文我们来给大家介绍下通过MyCat来实现MySQL的读写分离操作 MyCat读写分离 一.读写分离配置 前面我们已经介绍过了mysql的主从同步和mycat的安装及相关配置文件的介绍,现在我们来 ...