SPOJ 8222 Substrings
题面
Description
给长度为 n 的字符串 S , 对任意的 L , 求长度为 L 的子串最多出现的次数.
Input
String S consists of at most 250000 lowercase latin letters.
Output
Output |S| lines. On the i-th line output F(i).
Sample Input
ababa
Sample Output
3
2
2
1
1
题解
后缀自动机统计子串出现次数的应用.
考虑我们插入一个节点时, 其suffix link上的所有节点所代表的字符串的出现次数都+1, 因此parent tree上一个节点所代表的字符串的出现次数等于以它为根的子树中实点的出现次数.
线段树上成段更新来维护即可.
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
const int LEN = 250000;
struct segmentTree
{
int a[LEN << 2];
inline segmentTree()
{
memset(a, 0, sizeof(a));
}
void modify(int u, int curL, int curR, int L, int R, int w)
{
if(curL >= L && curR <= R)
{
a[u] = std::max(a[u], w);
return;
}
int mid = curL + curR >> 1;
if(L <= mid)
modify(u << 1, curL, mid, L, R, w);
if(R > mid)
modify(u << 1 | 1, mid + 1, curR, L, R, w);
}
inline void modify(int L, int R, int w)
{
modify(1, 1, LEN, L, R, w);
}
int query(int u, int L, int R, int pos)
{
if(L == R)
return a[u];
int mid = L + R >> 1;
if(pos <= mid)
return std::max(a[u], query(u << 1, L, mid, pos));
else
return std::max(a[u], query(u << 1 | 1, mid + 1, R, pos));
}
inline int query(int pos)
{
return query(1, 1, LEN, pos);
}
}sgt;
struct suffixAutomaton
{
struct state
{
state *suc[26], *pre;
std::vector<state*> sucOnTr;
int len, sz, tg;
inline state()
{
for(int i = 0; i < 26; ++ i)
suc[i] = NULL;
sucOnTr.clear();
sz = tg = 0;
}
};
state *rt, *lst;
inline void insert(int c)
{
state *u = new state;
u->len = lst->len + 1;
u->sz = 1;
for(; lst != NULL && lst->suc[c] == NULL; lst->suc[c] = u, lst = lst->pre);
if(lst == NULL)
u->pre = rt;
else
{
state *p = lst->suc[c];
if(p->len == lst->len + 1)
u->pre = p;
else
{
state *q = new state;
*q = *p;
q->sz = 0;
q->len = lst->len + 1;
p->pre = u->pre = q;
for(; lst != NULL && lst->suc[c] == p; lst->suc[c] = q, lst = lst->pre);
}
}
lst = u;
}
inline void build(char *str, int len)
{
lst = rt = new state;
rt->len = 0, rt->pre = NULL;
for(int i = 0; i < len; ++ i)
insert(str[i] - 'a');
}
void getSucessorOnSuffixTree(state *u)
{
u->tg = 1;
if(u->pre != NULL)
u->pre->sucOnTr.push_back(u);
for(int i = 0; i < 26; ++ i)
if(u->suc[i] != NULL && ! u->suc[i]->tg)
getSucessorOnSuffixTree(u->suc[i]);
}
void DFS(state *u)
{
for(std::vector<state*>::iterator p = u->sucOnTr.begin(); p != u->sucOnTr.end(); ++ p)
DFS(*p), u->sz += (*p)->sz;
if(u != rt)
sgt.modify(u->pre->len + 1, u->len, u->sz);
}
inline void work()
{
getSucessorOnSuffixTree(rt);
DFS(rt);
}
}SAM;
int main()
{
#ifndef ONLINE_JUDGE
freopen("SPOJ8222.in", "r", stdin);
#endif
static char str[LEN];
scanf("%s", str);
int len = strlen(str);
SAM.build(str, len);
SAM.work();
for(int i = 1; i <= len; ++ i)
printf("%d\n", sgt.query(i));
}
SPOJ 8222 Substrings的更多相关文章
- spoj 8222 Substrings (后缀自动机)
spoj 8222 Substrings 题意:给一个字符串S,令F(x)表示S的所有长度为x的子串中,出现次数的最大值.求F(1)..F(Length(S)) 解题思路:我们构造S的SAM,那么对于 ...
- SPOJ 8222 Substrings(后缀自动机)
[题目链接] http://www.spoj.com/problems/NSUBSTR/ [题目大意] 给一个字符串S,令F(x)表示S的所有长度为x的子串中,出现次数的最大值. 求出所有的F. [题 ...
- spoj 8222 Substrings(后缀自动机+DP)
[题目链接] http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=28005 [题意] 给一个字符串S,令F(x)表示S的所有长度为 ...
- SPOJ 8222. Substrings(后缀自动机模板)
后缀自动机+dp. 后缀自动机主要是在functioner大牛那里学习的:http://blog.sina.com.cn/s/blog_70811e1a01014dkz.html 这道题是在No_st ...
- 【SPOJ】Substrings(后缀自动机)
[SPOJ]Substrings(后缀自动机) 题面 Vjudge 题意:给定一个长度为\(len\)的串,求出长度为1~len的子串中,出现最多的出现了多少次 题解 出现次数很好处理,就是\(rig ...
- 【SPOJ 8222】Substrings
http://www.spoj.com/problems/NSUBSTR/ clj课件里的例题 用结构体+指针写完模板后发现要访问所有的节点,改成数组会更方便些..于是改成了数组... 这道题重点是求 ...
- ●SPOJ 8222 NSUBSTR–Substrings
题链: http://www.spoj.com/problems/NSUBSTR/题解: 后缀自动机. 不难发现,对于自动机里面的一个状态s, 如果其允许的最大长度为maxs[s],其right集合的 ...
- ●SPOJ 8222 NSUBSTR - Substrings(后缀数组)
题链: http://www.spoj.com/problems/NSUBSTR/ 题解: 同届红太阳 --WSY给出的后缀数组解法!!! 首先用倍增算法求出 sa[i],rak[i],hei[i]然 ...
- ●SPOJ 8222 NSUBSTR–Substrings(后缀自动机)
题链: http://www.spoj.com/problems/NSUBSTR/ 题解: 后缀自动机的水好深啊!懂不了相关证明,带着结论把这个题做了.看来这滩深水要以后再来了. 本题要用到一个叫 R ...
随机推荐
- printk的使用技巧
在 linux/kernel.h 中有相应的宏对应. #define KERN_EMERG "<0>" /* system is unusable */#d ...
- LeetCode(292) Nim Game
题目 You are playing the following Nim Game with your friend: There is a heap of stones on the table, ...
- Linux编程中链接库的使用
链接库本质上是一段可执行的二进制代码,可以被操作系统载入内存执行.按加载的时机不同,链接库可以分为静态链接库和动态链接库. 静态链接库:编译过程中加载进可执行文件的库(静态库省去了运行时加载的消耗,但 ...
- JAVA-基础(一)
1.一个变量可以声明为final,这样做的目的是阻止它的内容被修改.这意味着在声明final 变量的时候,你必须初始化它(在这种用法上,final类似于C/C++中的const). 例如: final ...
- python闭包函数、装饰器
闭包函数的传值方式: 方式1:通过参数传值 def func(x): print(x)func(1) 方式2:闭包函数传值 def outter(x): def inner(): print(x) r ...
- C语言知识点(4)
一.while. dowhile. 1.while while (表达式) { 语句: … 语句: } 2.while do { printf(“%d/n,I);…}while (i<=1 ...
- python 计算日期间隔
from datetime import date a = date(2011,11,24) b = date(2011,11,17) print(a-b)
- Map容器——TreeMap及常用API,Comparator和Comparable接口
TreeMap及常用API ① TreeMap类通过使用红黑树实现Map接口; ② TreeMap提供按排序顺序存储键/值对的有效手段,同时允许快速检索; ③ 不像散列(HashMap), ...
- ABP介绍
ABP是ASP.NET Boilerplate Project (ASP.NET样板项目)的简称. ABP 适用的场景:中小规模 WEB 应用开发,可直接使用 ABP 框架. 较大型项目可以在 ABP ...
- 九度oj 题目1080:进制转换
题目描述: 将M进制的数X转换为N进制的数输出. 输入: 输入的第一行包括两个整数:M和N(2<=M,N<=36). 下面的一行输入一个数X,X是M进制的数,现在要求你将M进制的数X转换成 ...