BZOJ 2882: 工艺( 后缀自动机 )

把串S复制成SS然后扔进后缀自动机里, 从根选最小的儿子走, 走N步就是答案了...一开始还想写个treap的...后来觉得太麻烦..就用map了...

---------------------------------------------------------------------------

#include<cstdio>

#include<cstring>

#include<algorithm>

#include<map>

using namespace std;

const int maxn = 300009;

struct Node {

Node* fa;

map<int, Node*> ch;

int len;

} pool[maxn << 2], *pt = pool, *root, *last;

Node* newNode(int v) {

pt->fa = NULL;

pt->ch.clear();

pt->len = v;

return pt++;

}

void init() {

pt = pool;

root = last = newNode(0);

}

void Extend(int c) {

Node *p = last, *np = newNode(p->len + 1);

for(; p && !p->ch[c]; p = p->fa)

p->ch[c] = np;

if(!p)

np->fa = root;

else {

Node* q = p->ch[c];

if(p->len + 1 == q->len)

np->fa = q;

else {

Node* nq = newNode(p->len + 1);

nq->fa = q->fa;

q->fa = np->fa = nq;

for(map<int, Node*>::iterator it = q->ch.begin(); it != q->ch.end(); it++)

nq->ch[it->first] = it->second;

for(; p && p->ch[c] == q; p = p->fa)

p->ch[c] = nq;

}

}

last = np;

}

int N, num[maxn];

int main() {

init();

scanf("%d", &N);

for(int i = 0; i < N; i++)

scanf("%d", num + i);

for(int i = 0; i < 2; i++)

for(int j = 0; j < N; j++)

Extend(num[j]);

for(int i = 0; i < N; i++) {

map<int, Node*>::iterator it = root->ch.begin();

if(i) putchar(‘ ‘);

printf("%d", it->first);

root = it->second;

}

return 0;

}

---------------------------------------------------------------------------

2882: 工艺

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 268  Solved: 108
[Submit][Status][Discuss]

Description

小敏和小燕是一对好朋友。

他们正在玩一种神奇的游戏,叫Minecraft。

他们现在要做一个由方块构成的长条工艺品。但是方块现在是乱的,而且由于机器的要求,他们只能做到把这个工艺品最左边的方块放到最右边。

他们想,在仅这一个操作下,最漂亮的工艺品能多漂亮。

两个工艺品美观的比较方法是,从头开始比较,如果第i个位置上方块不一样那么谁的瑕疵度小,那么谁就更漂亮,如果一样那么继续比较第i+1个方块。如果全都一样,那么这两个工艺品就一样漂亮。

Input

第一行两个整数n,代表方块的数目。

第二行n个整数,每个整数按从左到右的顺序输出方块瑕疵度的值。

Output

一行n个整数,代表最美观工艺品从左到右瑕疵度的值。

Sample Input

10
10 9 8 7 6 5 4 3 2 1

Sample Output

1 10 9 8 7 6 5 4 3 2

HINT

【数据规模与约定】

对于20%的数据,n<=1000

对于40%的数据,n<=10000

对于100%的数据,n<=300000

Source

时间: 2024-10-11 10:17:01

BZOJ 2882: 工艺( 后缀自动机 )的相关文章

BZOJ 2555 SubString 后缀自动机

题目大意:给出一个字符串,支持在线在字符串后面加一个字符串,查询一个字符串在串中出现过几次. 思路:如果不想写正解的话,这个题就是后缀自动机的简单应用.正解其实是LCT+SAM,但是时间比暴力慢一倍... 暴力就很简单了,正序建立后缀自动机,每次查询的时候找到位置直接输出size的值.注意两点,一个是分裂节点的时候,size也要复制过去.查询的时候发现找不到要return 0; CODE: #include <cstdio> #include <cstring> #include

【bzoj2882】工艺 后缀自动机+STL-map

题目描述 小敏和小燕是一对好朋友. 他们正在玩一种神奇的游戏,叫Minecraft. 他们现在要做一个由方块构成的长条工艺品.但是方块现在是乱的,而且由于机器的要求,他们只能做到把这个工艺品最左边的方块放到最右边. 他们想,在仅这一个操作下,最漂亮的工艺品能多漂亮. 两个工艺品美观的比较方法是,从头开始比较,如果第i个位置上方块不一样那么谁的瑕疵度小,那么谁就更漂亮,如果一样那么继续比较第i+1个方块.如果全都一样,那么这两个工艺品就一样漂亮. 输入 第一行两个整数n,代表方块的数目. 第二行n

bzoj 2555 SubString —— 后缀自动机+LCT

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2555 建立后缀自动机,就可以直接加入新串了: 出现次数就是 Right 集合的大小,需要查询 Parent 树上的子树和: 所以可以用 LCT 维护 Parent 树,因为 Parent 树是有根树所以不需要 makeroot: 代码中的两种 cut 写法都可以,其实这里的 splay 节点上记的 siz 值不是 splay 子树里的而是原子树( Parent 树上)里的: 注意读入的函数

BZOJ 2555 Substring 后缀自动机+Link-Cut-Tree

题目大意:给定一个初始字符串,提供两种操作: 1.在这个字符串的后面连接一个字符串 2.询问某个字符串在当前串中出现了多少次 SAM大叔的自动机~~ 对于每个询问就是在后缀自动机上找到该子串所对应的节点 找不到返回0 然后这个节点的Right集合的大小就是这个子串的出现次数 每次Extend的时候将新建节点沿着parent指针到根的路径上所有点的Right集合大小+1即可 分裂节点的时候要将Right集合一并复制 这方法虽然暴力但是非常有效 由于parent是一棵树,所以可以用LCT来维护这棵树

BZOJ 2555: SubString [后缀自动机 LCT]

2555: SubString Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 2045  Solved: 583[Submit][Status][Discuss] Description 懒得写背景了,给你一个字符串init,要求你支持两个操作        (1):在当前字符串的后面插入一个字符串        (2):询问字符串s在当前字符串中出现了几次?(作为连续子串)        你必须在线支持这些操作. Input 第一行一个数Q表示

bzoj 2555 SubString——后缀自动机+LCT

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2555 要维护 right 集合的大小.因为 fa 会变,且 fa 构成一棵树,所以考虑用 LCT 来维护-- 和平常写的 LCT 不太一样.因为要的值是原树上子树里的值,所以没有 makeroot ,splay 里不维护 splay 里的子树信息,只维护加法标记,表示 link 一下就给原树的自己到根的那条链上的所有点加了自己的值.cut 就是减掉自己的值.所以 query 或者 spla

bzoj 3413: 匹配 后缀自动机+线段树合并

并不是很难啊,把细节想好了再写就很轻松了~ code: #include <bits/stdc++.h> #define N 200003 #define LL long long #define setIO(s) freopen(s".in","r",stdin) ,freopen(s".out","w",stdout) using namespace std; struct SAM { int tot,last

bzoj 5408: string 后缀自动机+动态树

联赛前练练码力. code: #include <vector> #include <cstdio> #include <cstring> #include <algorithm> #define N 200006 #define ll long long #define lson t[x].ch[0] #define rson t[x].ch[1] #define setIO(s) freopen(s".in","r"

后缀自动机习题合集

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