ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

P2870 [USACO07DEC]Best Cow Line G(后缀数组)

2020-10-11 20:01:35  阅读:253  来源: 互联网

标签:Cow wb1 ++ int P2870 wa1 tbc sa USACO07DEC


题目链接
题意:给你一个字符串,每次从首或尾取一个字符组成字符串,问所有能够组成的字符串中字典序最小的一个。
思路:首先定义两个指针L和R,如果s[L]<s[R],肯定选s[R],s[L]>s[R],选s[R].对于s[L]==s[R]的情况,可以考虑L位置的rank以及R位置反串的rank值大小。所以还需要将s的反串构造进去,建立后缀数组。
突然发现其实就一种,因为如果s[L]<s[R],那么rank[l]一定也小于反串的r的rank值。


#include <iostream>
#include <stdio.h>
#include <cstring>
#include <algorithm>
using namespace std;
#define Max_N 1000100
#define F(x) ((x)/3+((x)%3==1?0:tb))
#define G(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2) 
int wa1[Max_N*3], wb1[Max_N*3], wv1[Max_N*3], ws1[Max_N*3]; 
int c0(int *r, int a, int b)  
{
	return r[a] == r[b] && r[a+1] == r[b+1] && r[a+2] == r[b+2];
}
 
int c12(int k, int *r, int a, int b) 
{
	if(k == 2) return r[a] < r[b] || r[a] == r[b] && c12(1, r, a+1, b+1); 
    else return r[a] < r[b] || r[a] == r[b] && wv1[a+1] < wv1[b+1];
}
    
 void sort(int *r, int *a, int *b, int n, int m) 
 { 
	int i; 
	for (i = 0; i < n; i++) wv1[i] = r[a[i]]; 
	for (i = 0; i < m; i++) ws1[i] = 0; 
	for (i = 0; i < n; i++) ws1[wv1[i]]++; 
	for (i = 1; i < m; i++) ws1[i] += ws1[i-1]; 
	for (i = n-1; i >= 0; i--) b[--ws1[wv1[i]]] = a[i]; 
	return; 
 }
void dc3(int *r, int *sa, int n, int m)
{
	int i, j, *rn = r + n, *san = sa + n,ta = 0,tb = (n + 1) / 3,tbc = 0,p; 
    r[n] = r[n+1] = 0; 
    for (i = 0; i < n; i++) if (i % 3 != 0) wa1[tbc++] = i; 
    sort(r+2, wa1, wb1, tbc, m); 
    sort(r+1, wb1, wa1, tbc, m); 
    sort(r, wa1, wb1, tbc, m); 
    for (p = 1,rn[F(wb1[0])] = 0,i = 1;i < tbc; i++) 
    rn[F(wb1[i])] = c0(r, wb1[i-1], wb1[i]) ? p - 1 : p++; 
    if (p < tbc) dc3(rn, san, tbc, p); 
    else for (i = 0; i < tbc; i++) san[rn[i]] = i;
    for (i = 0; i < tbc; i++) if (san[i] < tb) wb1[ta++] = san[i] * 3; 
    if (n % 3 == 1) wb1[ta++] = n - 1; 
    sort(r, wb1, wa1, ta, m); 
    for (i = 0; i < tbc; i++) wv1[wb1[i] = G(san[i])] = i; 
    for (i = 0, j = 0, p = 0; i < ta && j < tbc; p++) 
    sa[p] = c12(wb1[j] % 3, r, wa1[i], wb1[j]) ? wa1[i++] : wb1[j++]; 
    for(; i < ta; p++) sa[p] = wa1[i++]; 
    for(; j < tbc; p++) sa[p] = wb1[j++]; 
    return; 
}
// str sa 都要开三倍的;
void da(int str[], int sa[], int rank1[], int height1[], int n, int m)
{
	for (int i = n; i < n*3; i++)
		str[i] = 0;
	dc3(str, sa, n+1, m);
	int i, j, k = 0;
	for (i = 0; i <= n; i++) rank1[sa[i]] = i;
	for (i = 0; i < n; i++)
	{
		if (k) k--;
		j = sa[rank1[i] - 1];
		while (str[i+k] == str[j+k]) k++;
		height1[rank1[i]] = k;
	}
	return;
}
char s[Max_N];
int str[3*Max_N];
int sa[3*Max_N];//sa[i]表示将所有后缀排序后第i小的后缀的编号。
int rank1[3*Max_N];//rank1[i]表示后缀i的排名。
int height1[3*Max_N];
char ans[Max_N];
int main()
{
	/*char buf[100];
	cin >> buf;
	int n = strlen(buf);
	//cout << n << endl;
	int m = 128;
	for (int i = 0; i < strlen(buf); i++)
		str[i] = int(buf[i]);
	str[n] = 0;
	da(str, sa, rank1, height1, n, m);
	for (int i = 0; i <= n; i++)
		cout << sa[i] << endl;
	return 0;
	*/
	int n;
	scanf("%d",&n);
	int k=0;
	for(int i=0;i<n;i++)
	{
		char a[2];
		scanf("%s",a);
		s[k++]=a[0];
	}
	s[k]='#';
	for(int i=0;i<k;i++)
	{
		s[k+i+1]=s[k-i-1];
	}
	k=2*n+1;
	for(int i=0;i<k;i++)
	{
		str[i]=int(s[i]);
	}
	str[k]=0;
	int m=128;
	da(str, sa, rank1, height1, k, m);
	int L=0,R=n-1;
	int cnt=0;
	while(L<=R)
	{
		if(s[L]<s[R])
		{
			ans[cnt++]=s[L];
			L++;
		}
		else if(s[L]>s[R])
		{
			ans[cnt++]=s[R];
			R--;
		}
		else
		{
			int m=(n-R);
			if(rank1[L]>rank1[n+m])
			{
				ans[cnt++]=s[R];
				R--;
			}
			else
			{
				ans[cnt++]=s[L];
				L++;
			}
		}
	}
	ans[cnt]='\0';
	int tot=0;
	for(int i=0;i<cnt;i++)
	{
		printf("%c",ans[i]);
		tot++;
		if(tot%80==0)
		{
			printf("\n");
		}
	}
 
}

标签:Cow,wb1,++,int,P2870,wa1,tbc,sa,USACO07DEC
来源: https://www.cnblogs.com/2462478392Lee/p/13798961.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有