[SPOJ8222]Substrings

试题描述

You are given a string S which consists of 250000 lowercase latin letters at most. We define F(x) as the maximal number of times that some string with length x appears in S. For example for string ‘ababa‘ F(3) will be 2 because there is a string ‘aba‘ that occurs twice. Your task is to output F(i) for every i so that 1<=i<=|S|.

输入

String S consists of at most 250000 lowercase latin letters.

输出

Output |S| lines. On the i-th line output F(i).

输入示例

ababa

输出示例

3
2
2
1
1

数据规模及约定

见“输入

题解

构造后缀自动机,然后用每个节点 i 的 righti 集合大小更新 f[Max[i]],然后再用每个 f[i] 更新 f[i-1]。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
using namespace std;

int read() {
	int x = 0, f = 1; char c = getchar();
	while(!isdigit(c)){ if(c == ‘-‘) f = -1; c = getchar(); }
	while(isdigit(c)){ x = x * 10 + c - ‘0‘; c = getchar(); }
	return x * f;
}

#define maxn 500010
#define maxa 26

int n;
int ToT, rt, last, ch[maxn][maxa], par[maxn], Max[maxn], siz[maxn];
void extend(int x) {
	int p = last, np = ++ToT; Max[np] = Max[p] + 1; siz[np] = 1;
	last = np;
	while(p && !ch[p][x]) ch[p][x] = np, p = par[p];
	if(!p){ par[np] = rt; return ; }
	int q = ch[p][x];
	if(Max[q] == Max[p] + 1){ par[np] = q; return ; }
	int nq = ++ToT; Max[nq] = Max[p] + 1;
	memcpy(ch[nq], ch[q], sizeof(ch[q]));
	par[nq] = par[q];
	par[q] = nq;
	par[np] = nq;
	while(p && ch[p][x] == q) ch[p][x] = nq, p = par[p];
	return ;
}

int f[maxn];
char Str[maxn];
int sa[maxn], Ws[maxn];
void build() {
	for(int i = 1; i <= ToT; i++) Ws[n-Max[i]]++;
	for(int i = 1; i <= n; i++) Ws[i] += Ws[i-1];
	for(int i = ToT; i; i--) sa[Ws[n-Max[i]]--] = i;
	for(int i = 1; i <= ToT; i++) siz[par[sa[i]]] += siz[sa[i]];
	return ;
}

int main() {
	scanf("%s", Str); n = strlen(Str);
	rt = last = ToT = 1;
	for(int i = 0; i < n; i++) extend(Str[i] - ‘a‘);

	build();
	for(int i = 1; i <= ToT; i++) f[Max[i]] = max(f[Max[i]], siz[i]);
	for(int i = n; i > 1; i--) f[i-1] = max(f[i], f[i-1]);

	for(int i = 1; i <= n; i++) printf("%d\n", f[i]);

	return 0;
}
时间: 2024-10-12 00:20:55

[SPOJ8222]Substrings的相关文章

SPOJ8222 Substrings( 后缀自动机 + dp )

题目大意:给一个字符串S,令F(x)表示S的所有长度为x的子串中,出现次数的最大值.F(1)..F(Length(S)) 建出SAM, 然后求出Right, 求Right可以按拓扑序dp..Right就是某个点到结束状态的路径数, parent树上last的那一条链都是结束状态...然后用Right去更新答案.. spoj卡常数..一开始用DFS就炸了, 改用BFS就A了.. (贴一下丽洁姐的题解: 我们构造S的SAM,那么对于一个节点s,它的长度范围是[Min(s),Max(s)],同时他的出

后缀自动机习题合集

(写的都是初中小朋友czl早就切过的题……) http://www.cnblogs.com/Lyush/p/3281546.html POJ-1509 Glass Beads UVA - 719 Glass Beads 题意:一个字符串可以将第一个字符放到最后一位,然后问不断这样做可以得到的字典序最小的字符串 sam模板题,copy一遍建个sam,然后直接在sam中跑一遍就行了. sam记录了字符串的所有后缀(也随便记录了字串),从root开始到每个接受态节点都是一个后缀(或多个),从root开

【spoj8222】 Substrings

http://www.spoj.com/problems/NSUBSTR/ (题目链接) 题意 给出一个字符串S,令${F(x)}$表示S的所有长度为x的子串出现次数的最大值.求${F(1)......F(length(S))}$ Solution 后缀自动机例题,下面写几点自己认为理解后缀自动机的重点. 后缀自动机相对于后缀树就是将Right集合相同的子串合用一个节点来表示.每一个节点代表一个状态S,这个状态可能包含很多长度区间连续的子串,这些子串的右端点固定,它们的Right集合相同. 往上

[SPOJ8222]NSUBSTR - Substrings 后缀自动机

1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 int sz=0,la,rt; 6 int ch[500010][26],l[500010],fa[500010]; 7 void Extend(int c){ 8 int end=++sz,tmp=la; 9 l[end]=l[tmp]+1; 10 while(tmp&&!ch[tm

【spoj8222】Substrings

1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #define maxn 500005 7 #define maxm 250005 8 using namespace std; 9 10 int n,tot,root,last,f[maxm],fa[maxn],son[maxn][2

SPOJ8222/NSUBSTR:Substrings——题解

https://www.luogu.org/problemnew/show/SP8222#sub http://www.spoj.com/problems/NSUBSTR/ 翻译来自洛谷. 你得到一个字符串,最多由25万个小写拉丁字母组成.我们将 F(x)定义为某些长度X的字符串在s中出现的最大次数,例如字符串'ababaf'- F(x),因为有一个字符串'ABA'出现两次.你的任务是输出 F(x)每一个I,以使1<=i<=|S|. water! 后缀自动机后对l排个序,对每个l更新其ans就

SPOJ8222 NSUBSTR - Substrings 后缀自动机_动态规划

讲起来不是特别好讲.总之,如果 $dp[i+1]>=dp[i]$,故$dp[i]=max(dp[i],dp[i+1])$ Code: #include <cstdio> #include <algorithm> #include <cstring> #define setIO(s) freopen(s".in","r",stdin) #define maxn 2000000 #define N 30 #define ll l

【SPOJ8222】Substrings (后缀自动机)

题意: 给一个字符串S,令F(x)表示S的所有长度为x的子串中,出现次数的最大值. 求F(1)..F(Length(S)) Length(S) <= 250000 思路:板子中st[x]定义为root到x的最多步数,可以用来更新所有长度为[1..st[x]]的答案 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 typedef unsigned int uint; 5 typedef u

[Leetcode] DP-- 467. Unique Substrings in Wraparound String

Consider the string s to be the infinite wraparound string of "abcdefghijklmnopqrstuvwxyz", so s will look like this: "...zabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd....". Now we have another string p. Your job is to find