POJ 题目3581 Sequence(后缀数组)

Sequence

Time Limit: 5000MS   Memory Limit: 65536K
Total Submissions: 5738   Accepted: 1227
Case Time Limit: 2000MS

Description

Given a sequence, {A1, A2, ..., An} which is guaranteed
A1 > A2, ..., An,  you are to cut it into three sub-sequences and reverse them separately to form a new one which is the smallest possible sequence in alphabet order.

The alphabet order is defined as follows: for two sequence {A1,
A2, ..., An} and {B1,
B2, ..., Bn}, we say {A1,
A2, ..., An} is smaller than {B1,
B2, ..., Bn} if and only if there exists such
i ( 1 ≤ in) so that we have Ai <
Bi and Aj = Bj for each j <
i.

Input

The first line contains n. (n ≤ 200000)

The following n lines contain the sequence.

Output

output n lines which is the smallest possible sequence obtained.

Sample Input

5
10
1
2
3
4

Sample Output

1
10
2
4
3

Hint

{10, 1, 2, 3, 4} -> {10, 1 | 2 | 3, 4} -> {1, 10, 2, 4, 3}

Source

POJ Founder Monthly Contest – 2008.04.13, Yao Jinyu

解析转自:http://blog.csdn.net/whyorwhnt/article/details/9840641

题意:给定一个数列,将其分为非空的三段。然后分别将三段的数字翻转连接在一起组成新的数列。输出处理后字典序最小的结果。

思路:首先注意必须写成单Case的形式!!!while(scanf("%d",&n)!=EOF)会RE或者WA。。。

因为要翻转,所以读入时直接反着读。由于没有告诉数值的上限,所以接下来离散化。

对于第一段:第一段翻转之后必须最小,因此对翻转过的数列求sa,则排名在前面且sa[i]>1(因为另两段不能为空)的第一个i为第一段。

接下来处理后两段:显然要让第二段的开头尽可能小,但是切去第二段后剩下的部分会直接接在第二段后面,所以不能直接求sa。为保证第三段接在第二段后面时整体最小,所以需要把剩余的串复制到剩余串的后面,再求sa.注意数组要开2倍。

以下举例转自 poj3581 Sequence(后缀数组) - Damonbaby的日志 - 网易博客

刚开始的时候觉得没有必要将剩下的数字复制一片贴在剩下的数字后面,所以wa了很多次。。。

最后在discuss里面看见一组数据:

9

8 4 -1 5 0 5 0 2 3

第一步:

3 2 0 5 0 5 -1 4 8 对应输出 -1 4 8

第二步

3 2 0 5 0 5(开始的时候我并没有复制一遍) 对应输出:0 5

第三步

3 2 0 5    对应输出: 3 2 0 5

可以看见这样做是不对的。。

必须要将剩下的字符串复制一遍贴在后面,然后再来求后缀数组。。。

正解:

第一步:

3 2 0 5 0 5 -1 4 8 对应输出 -1 4 8

第二步

3 2 0 5 0 5 3 2 0 5 0 5 对应输出: 0 5 0 5;

第三步

3 2 对应输出:3 2;

ac代码

Problem: 3581  User: kxh1995
Memory: 8020K  Time: 2032MS
Language: C++  Result: Accepted
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
#include<iostream>
#define min(a,b) (a>b?b:a)
#define max(a,b) (a>b?a:b)
#define INF 0xfffffff
using namespace std;
int sa[400010],Rank[400010],rank2[400010],c[400010],*x,*y,s[400010],k,temp[400010],num[400010];
void cmp(int n,int sz)
{
    int i;
    memset(c,0,sizeof(c));
    for(i=0;i<n;i++)
        c[x[y[i]]]++;
    for(i=1;i<sz;i++)
        c[i]+=c[i-1];
    for(i=n-1;i>=0;i--)
        sa[--c[x[y[i]]]]=y[i];
}
void build_sa(int *s,int n,int sz)
{
    x=Rank,y=rank2;
    int i,j;
    for(i=0;i<n;i++)
        x[i]=s[i],y[i]=i;
    cmp(n,sz);
    int len;
    for(len=1;len<n;len<<=1)
    {
        int yid=0;
        for(i=n-len;i<n;i++)
        {
            y[yid++]=i;
        }
        for(i=0;i<n;i++)
            if(sa[i]>=len)
                y[yid++]=sa[i]-len;
            cmp(n,sz);
			swap(x,y);
			x[sa[0]]=yid=0;
			for(i=1;i<n;i++)
			{
				if(y[sa[i-1]]==y[sa[i]]&&sa[i-1]+len<n&&sa[i]+len<n&&y[sa[i-1]+len]==y[sa[i]+len])
					x[sa[i]]=yid;
				else
					x[sa[i]]=++yid;
			}
			sz=yid+1;
			if(sz>=n)
				break;
    }
    for(i=0;i<n;i++)
        Rank[i]=x[i];
}
struct s
{
	int val,id;
}a[200020];
int cmp(const void *a,const void *b)
{
	return (*(struct s *)a).val-(*(struct s *)b).val;
}
int main()
{
	int n;
	scanf("%d",&n);
		int i;
		for(i=n-1;i>=0;i--)
		{
			scanf("%d",&num[i]);
			a[i].val=num[i];
			a[i].id=i;
		}
		qsort(a,n,sizeof(a[0]),cmp);
		temp[0]=1;
		for(i=1;i<n;i++)
		{
			temp[i]=(a[i].val==a[i-1].val?temp[i-1]:i+1);
		}
		for(i=0;i<n;i++)
		{
			s[a[i].id]=temp[i];
		}
		s[n]=0;
		build_sa(s,n+1,n+5);
		int minn=INF;
		for(i=1;i<=n;i++)
		{
			if(sa[i]>1)
				break;
		}
		int m=sa[i];
		for(i=m;i<n;i++)
		{
			printf("%d\n",num[i]);
		}
		for(i=0;i<m;i++)
		{
			s[m+i]=s[i];
		}

		int nn=m*2;
		s[nn]=0;
		//for(i=0;i<nn;i++)
		//	{
		//		printf("****%d\n",s[i]);
		//	}
		build_sa(s,nn+1,n+5);
		for(i=1;i<=nn;i++)
		{
			if(sa[i]>0&&sa[i]<m)
				break;
		}
		int j;
		for(j=sa[i];j<m;j++)
		{
			printf("%d\n",num[j]);
		}
		for(j=0;j<sa[i];j++)
		{
			printf("%d\n",num[j]);
		}
	//	while(1);
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-11 21:54:00

POJ 题目3581 Sequence(后缀数组)的相关文章

POJ 3294 Life Forms (后缀数组)

题目大意: 求出在m个串中出现过大于m/2次的子串. 思路分析: 如果你只是直接跑一次后缀数组,然后二分答案扫描的话. 那么就试一下下面这个数据. 2 abcdabcdefgh efgh 这个数据应该输出 efgh 问题就在于对于每一个串,都只能参与一次计数,所以在check的时候加一个标记数组是正解. #include <cstdio> #include <iostream> #include <algorithm> #include <cstring>

POJ 3882 Stammering Aliens 后缀数组height应用

题目来源:POJ 3882 Stammering Aliens 题意:给你m一个一个字符串 求至少出现m次的最长字符串 可以在字符串中重叠出现 思路:二分长度l 然后从height数组中找长度大于等于l的前缀 #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 40010; char s[maxn]; int sa[maxn]; i

Sequence POJ - 3581 (后缀数组)

Given a sequence, {A1, A2, ..., An} which is guaranteed A1 > A2, ..., An,  you are to cut it into three sub-sequences and reverse them separately to form a new one which is the smallest possible sequence in alphabet order. The alphabet order is defin

POJ 1743 Musical Theme 后缀数组 最长重复不相交子串

Musical ThemeTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://poj.org/problem?id=1743 Description A musical melody is represented as a sequence of N (1<=N<=20000)notes that are integers in the range 1..88, each representing a key on the piano. It

poj 3261 Milk Patterns 后缀数组+二分

1 /*********************************************************** 2 题目: Milk Patterns(poj 3261) 3 链接: http://poj.org/problem?id=3261 4 题意: 给一串数字,求这些数字中公共子串个数大于k的 5 最长串. 6 算法: 后缀数组+二分 7 ***********************************************************/ 8 #incl

POJ - 1743 Musical Theme (后缀数组求不可重叠最长重复子串)

Description A musical melody is represented as a sequence of N (1<=N<=20000)notes that are integers in the range 1..88, each representing a key on the piano. It is unfortunate but true that this representation of melodies ignores the notion of music

Poj 3294 Life Forms (后缀数组 + 二分 + Hash)

题目链接: Poj 3294 Life Forms 题目描述: 有n个文本串,问在一半以上的文本串出现过的最长连续子串? 解题思路: 可以把文本串用没有出现过的不同字符连起来,然后求新文本串的height.然后二分答案串的长度K,根据K把新文本串的后缀串分块,统计每块中的原文本串出现的次数,大于原文本串数目的一半就作为答案记录下来,对于输出字典序,height就是排好序的后缀数组,只要按照顺序输出即可. 1 #include <cstdio> 2 #include <cstring>

poj 1743 Musical Theme(后缀数组)

Musical Theme Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 30544   Accepted: 10208 Description A musical melody is represented as a sequence of N (1<=N<=20000)notes that are integers in the range 1..88, each representing a key on the

poj 1743 Musical Theme 后缀数组

题目链接 做出公差后找出最长不重叠子序列的长度. 后缀数组的模板, 二分长度k然后将height数组分组, 判断每一组内sa的最大值-sa的最小值是否大于等于k, 如果大于等于k则满足. 1 #include <iostream> 2 #include <vector> 3 #include <cstdio> 4 #include <cstring> 5 #include <algorithm> 6 #include <cmath>