题面

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的更多相关文章

  1. spoj 8222 Substrings (后缀自动机)

    spoj 8222 Substrings 题意:给一个字符串S,令F(x)表示S的所有长度为x的子串中,出现次数的最大值.求F(1)..F(Length(S)) 解题思路:我们构造S的SAM,那么对于 ...

  2. SPOJ 8222 Substrings(后缀自动机)

    [题目链接] http://www.spoj.com/problems/NSUBSTR/ [题目大意] 给一个字符串S,令F(x)表示S的所有长度为x的子串中,出现次数的最大值. 求出所有的F. [题 ...

  3. spoj 8222 Substrings(后缀自动机+DP)

    [题目链接] http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=28005 [题意] 给一个字符串S,令F(x)表示S的所有长度为 ...

  4. SPOJ 8222. Substrings(后缀自动机模板)

    后缀自动机+dp. 后缀自动机主要是在functioner大牛那里学习的:http://blog.sina.com.cn/s/blog_70811e1a01014dkz.html 这道题是在No_st ...

  5. 【SPOJ】Substrings(后缀自动机)

    [SPOJ]Substrings(后缀自动机) 题面 Vjudge 题意:给定一个长度为\(len\)的串,求出长度为1~len的子串中,出现最多的出现了多少次 题解 出现次数很好处理,就是\(rig ...

  6. 【SPOJ 8222】Substrings

    http://www.spoj.com/problems/NSUBSTR/ clj课件里的例题 用结构体+指针写完模板后发现要访问所有的节点,改成数组会更方便些..于是改成了数组... 这道题重点是求 ...

  7. ●SPOJ 8222 NSUBSTR–Substrings

    题链: http://www.spoj.com/problems/NSUBSTR/题解: 后缀自动机. 不难发现,对于自动机里面的一个状态s, 如果其允许的最大长度为maxs[s],其right集合的 ...

  8. ●SPOJ 8222 NSUBSTR - Substrings(后缀数组)

    题链: http://www.spoj.com/problems/NSUBSTR/ 题解: 同届红太阳 --WSY给出的后缀数组解法!!! 首先用倍增算法求出 sa[i],rak[i],hei[i]然 ...

  9. ●SPOJ 8222 NSUBSTR–Substrings(后缀自动机)

    题链: http://www.spoj.com/problems/NSUBSTR/ 题解: 后缀自动机的水好深啊!懂不了相关证明,带着结论把这个题做了.看来这滩深水要以后再来了. 本题要用到一个叫 R ...

随机推荐

  1. leetcode-10-basic

    35. Search Insert Position Given a sorted array and a target value, return the index if the target i ...

  2. vscode设置让鼠标滚动改变字体大小

    打开settings.json文件 输入"editor.mouseWheelZoom": true, 这样比较方面,比默认的放大缩小来的快捷

  3. STM32三种启动模式 boot0 boot1

    STM32三种启动模式对应的存储介质均是芯片内置的,它们是: 1)用户闪存=芯片内置的Flash.2)SRAM=芯片内置的RAM区,就是内存啦.3)系统存储器=芯片内部一块特定的区域,芯片出厂时在这个 ...

  4. viewController备注

    1.按结构可以对iOS的所有ViewController分成两类: 1).主要用于展示内容的ViewController,这种ViewController主要用于为用户展示内容,并与用户交互,如UIT ...

  5. Linux学习-X Server 配置文件解析与设定

    X server 的配置 文件都是预设放置在 /etc/X11 目录下,而相关的显示模块或上面提到的总总模块,则主要放置在/usr/lib64/xorg/modules . 比较重要的是字型文件与芯片 ...

  6. 算法学习记录-查找——折半查找(Binary Search)

    以前有个游戏,一方写一个数字,另一方猜这个数字.比如0-100内一个数字,看谁猜中用的次数少. 这个里面用折半思想猜会大大减少次数. 步骤:(加入数字为9) 1.因为数字的范围是0-100,所以第一次 ...

  7. Hive学习笔记(四)-- hive的桶表

    桶表抽样查询 查看hdfs上对应的文件内容 一个两个桶,第一个桶和第三个桶的数据 task = 4 4 / 2 = 2,一共是两个桶 第1个桶,第1+2个桶

  8. 一个Work Stealing Pool线程池的实现

    一.一般来说实现一个线程池主要包括以下几个组成部分: 1)线程管理器 :用于创建并管理线程池 . 2)工作线程 :线程池中实际执行任务的线程 . 在初始化线程时会预先创建好固定数目的线程在池中 ,这些 ...

  9. GCC内嵌汇编一些限制字符串

    /******************/ “b”将输入变量放入ebx “c”将输入变量放入ecx “d”将输入变量放入edx “s”将输入变量放入esi “d”将输入变量放入edi “q”将输入变量放 ...

  10. Tensorflow 自适应学习速率

    Tensorflow 自适应学习速率 在模型的初期的时候,往往设置为较大的学习速率比较好,因为距离极值点比较远,较大的学习速率可以快速靠近极值点:而,后期,由于已经靠近极值点,模型快收敛了,此时,采用 ...