【最小表示法】BZOJ2882-工艺

【题目大意】

求一个循环数列的最小表示法。

【思路】

最小表示法模板题。之前用SAM做的,MLE了hhhhh戳

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 const int MAXN=300000+50;
 7 int s[MAXN*2],n;
 8
 9 void init()
10 {
11     scanf("%d",&n);
12     for (int i=0;i<n;i++)
13     {
14         scanf("%d",&s[i]);
15         s[i+n]=s[i];
16     }
17 }
18
19 void solve()
20 {
21     int i=0,j=1,k=0;
22     while (k<n)
23     {
24         int t=s[(i+k)%(2*n)]-s[(j+k)%(2*n)];//不要忘记了这里要mod
25         if (t==0) k++;
26         else
27         {
28             if (t>0) i+=k+1;
29                 else j+=k+1;
30             if (i==j) j++;
31             k=0;
32         }
33     }
34     for (int r=1,now=i;r<=k;r++,now=(now+1)%(2*n))
35     {
36         printf("%d",s[now]);
37         if (r!=k) printf(" ");
38     }
39 }
40
41 int main()
42 {
43     init();
44     solve();
45     return 0;
46 }
时间: 2024-10-06 02:43:46

【最小表示法】BZOJ2882-工艺的相关文章

bzoj2882工艺(最小表示法)

O(nlogn)的做法十分显然,有三种可以做到O(nlogn)的:1.最容易的想法:把串扩展成两倍,然后跑一遍SA求后缀数组.2.求后缀同样也可以用SAM去求解,用map存一下.3.最暴力的方法:直接二分+hash比较第一位不同的. 其实这题想要让我们用最小表示法求解,然而我不会就来学一下.很容易发现这样一个规律,如果存在s[i+k]>s[j+k],那么s[i...i+k]开头的都不会是最小表示法开头,因为s[i...i+k]=s[j...j+k],所以从s[i...i+k]开头的串都会经过这里

bzoj2882 工艺

2882: 工艺 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 488  Solved: 212 [Submit][Status][Discuss] Description 小敏和小燕是一对好朋友. 他们正在玩一种神奇的游戏,叫Minecraft. 他们现在要做一个由方块构成的长条工艺品.但是方块现在是乱的,而且由于机器的要求,他们只能做到把这个工艺品最左边的方块放到最右边. 他们想,在仅这一个操作下,最漂亮的工艺品能多漂亮. 两个工艺品美观的

HDU 4162 Shape Number(字符串,最小表示法)

HDU 4162 题意: 给一个数字串(length <= 300,000),数字由0~7构成,求出一阶差分码,然后输出与该差分码循环同构的最小字典序差分码. 思路: 第一步是将差分码求出:s[i] = (s[i] - s[i+1] + 8) % 8; 第二步是求出最小字典序的循环同构差分码,我之前没注意到字符串规模..直接用set做,MLE+TLE... 正确的方式应该是一种O(n)的解法,即最小表示法.//关于最小表示法的证明与详述请参考最小表示法:) 最小表示法算法: 初始时,i=0,j=

最小表示法(模板)

最小表示法就是对于一个循环字符串,其字典序最小的状态: 显然任意一个循环串的最小表示法是唯一的,那么可以同过比较两个循环串的最小表示法来判断它们是否相同: 对于朴素算法: 初始化:i = 0, j = 1, k = 0; 若 s[i] < s[j],j++: 若 s[i] > s[j],i = j, j++: 若 s[i] == s[j],则 k++,直至 s[i + k] != s[j + k] 对于 s[i + k] < s[j + k],j++: 否则 i = j, j++: 返回

USACO 5.5.2 字符串的最小表示法

这道题是最小表示法的一个应用, 代码如下: /* ID: m1500293 LANG: C++ PROG: hidden */ #include <cstdio> #include <algorithm> #include <cstring> using namespace std; char s[100000 + 100]; int len; int mins(char s[], int len) { int i=0, j=1, k=0; while(i<len

【枚举】【最小表示法】XVII Open Cup named after E.V. Pankratiev Stage 14, Grand Prix of Tatarstan, Sunday, April 2, 2017 Problem F. Matrix Game

给你一个n*m的字符矩阵,将横向(或纵向)全部裂开,然后以任意顺序首尾相接,然后再从中间任意位置切开,问你能构成的字典序最大的字符串. 以横向切开为例,纵向类似. 将所有横排从大到小排序,枚举最后切开的位置在哪一横排,将这一排提到排序后的字符串数组最前面,求个"最大表示法",如果最大表示法的位置恰好在第一排的位置,那么可以用来更新答案. 如果不在第一排的位置,那么其所构成的仍然是合法的串,而且一定不会影响答案. 这是一个最小表示法的板子. #include<cstdio>

BZOJ 2176 Strange string 最小表示法

题目大意:给定一个串S,求最小表示法 n<=1000W,实在不敢写后缀自己主动机,就去学了最小表示法= = 记得用unsigned char不然WA= = 数据真是逗- - #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 10001000 using namespace std; int n; unsigned char s[

循环字符串最大最小表示法模版

循环字符串最大最小表示法模版 定义字符串abcde和cdeab同构,因为abcde转两格即为cdeab,该字符串称为循环字符串. 循环字符串的字典序最小的同构字符串称为最小表示,最大表示同理. 这里只给模版,以后再深究. int getMin(char *s) ///返回首位置 { int n=strlen(s); int i=0,j=1,k=0; while(i<n&&j<n&&k<n){ int t=s[(i+k)%n]-s[(j+k)%n]; if(

hdu 2609 How many 最小表示法

How many Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1248    Accepted Submission(s): 486 Problem Description Give you n ( n < 10000) necklaces ,the length of necklace will not large than 100

51nod1282(最小表示法&amp;&amp;枚举)

题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1282 题意:中文题目诶- 思路:指针不可转,刻盘可转,显然,对于两组指针,当且仅当它们所有对应相邻指针间距都相等时是满足题意的: 先得到指针间距,因为刻盘可转,相当于循环数组,可以先求一下最小表示法,然后再两两枚举所有情况,对于最小表示法相同的两组指针,计数加一: 代码: 1 #include <iostream> 2 #include <algori