51nod-1732 婚姻介绍所(后缀数组)

题目大意:回答任意两个子串的最长公共前缀。

题目分析:后缀数组的模板题。但是输入输出都要外挂。

代码如下:

# include<iostream>
# include<cstdio>
# include<cstring>
# include<algorithm>
using namespace std;

const int N=1000;

int n,m;
char s[N+5];
int cnt[N+5],SA[N+5];
int rk[N+5],tSA[N+5];
int height[N+5];
int ans[N+5][N+5];

void in(int &x)
{
	x=0;
	char c=getchar();
	while(c<‘0‘||c>‘9‘){
		c=getchar();
	}
	x=c-‘0‘;
	while(c=getchar()){
		if(c<‘0‘||c>‘9‘) break;
		x=x*10+c-‘0‘;
	}
}

void out(int x)
{
	if(x>=10)
		out(x/10);
	putchar(x%10+‘0‘);
}

bool same(int *y,int i,int j,int k)
{
	if(y[SA[i]]!=y[SA[j]]) return false;
	if(SA[i]+k>=n&&SA[j]+k>=n) return true;
	if(SA[i]+k<n&&SA[j]+k>=n) return false;
	if(SA[i]+k>=n&&SA[j]+k<n) return false;
	return y[SA[i]+k]==y[SA[j]+k];
}

void buildSA()
{
	m=130;
	int *x=rk,*y=tSA;
	for(int i=0;i<m;++i) cnt[i]=0;
	for(int i=0;i<n;++i) ++cnt[x[i]=s[i]];
	for(int i=1;i<m;++i) cnt[i]+=cnt[i-1];
	for(int i=n-1;i>=0;--i) SA[--cnt[x[i]]]=i;
	for(int k=1;k<=n;k<<=1){
		int p=0;
		for(int i=n-k;i<n;++i) y[p++]=i;
		for(int i=0;i<n;++i) if(SA[i]>=k) y[p++]=SA[i]-k;
		for(int i=0;i<m;++i) cnt[i]=0;
		for(int i=0;i<n;++i) ++cnt[x[y[i]]];
		for(int i=1;i<m;++i) cnt[i]+=cnt[i-1];
		for(int i=n-1;i>=0;--i) SA[--cnt[x[y[i]]]]=y[i];
		p=1;
		swap(x,y);
		x[SA[0]]=0;
		for(int i=1;i<n;++i){
			if(same(y,i,i-1,k)) x[SA[i]]=p-1;
			else x[SA[i]]=p++;
		}
		if(p>=n) break;
		m=p;
	}
}

void getHeight()
{
	for(int i=0;i<n;++i)
		rk[SA[i]]=i;
	height[0]=0;
	for(int i=1;i<n;++i){
		int k=0;
		while(s[SA[i]+k]==s[SA[i-1]+k]) ++k;
		height[i]=k;
	}
}

void getAns()
{
	for(int i=0;i<n;++i) ans[i][i]=n-i;
	for(int i=0;i<n;++i){
		int minn=n;
		for(int j=i+1;j<n;++j){
			minn=min(minn,height[j]);
			ans[SA[i]][SA[j]]=ans[SA[j]][SA[i]]=minn;
		}
	}
}

int main()
{
	int q,a,b;
	while(~scanf("%d",&n))
	{
		scanf("%s",s);
		buildSA();
		getHeight();
		getAns();
		in(q);
		while(q--)
		{
			in(a);
			in(b);
			out(ans[a][b]);
			puts("");
		}
	}
	return 0;
}

  

时间: 2024-10-26 09:12:24

51nod-1732 婚姻介绍所(后缀数组)的相关文章

51nod 1732 婚姻介绍所 (暴力 / DP)

题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1732 题目: 51nod除了在做OJ之外,还开展了很多副业.婚姻介绍所就是其中之一. 对于一个客户,我们可以使用一个字符串来描述该客户的特质. 假设现在我们有两个客户A和B. A的特质字符串为:abcdefg B的特质字符串为:abcxyz 则A和B的匹配度f(A, B)为A和B的最长公共前缀的长度,即len('abc') = 3 由于最近51nod经费紧张,

51nod 1732 51nod婚姻介绍所

51nod除了在做OJ之外,还开展了很多副业.婚姻介绍所就是其中之一. 对于一个客户,我们可以使用一个字符串来描述该客户的特质. 假设现在我们有两个客户A和B. A的特质字符串为:abcdefg B的特质字符串为:abcxyz 则A和B的匹配度f(A, B)为A和B的最长公共前缀的长度,即len('abc') = 3 由于最近51nod经费紧张,所以夹克大老爷设计了一种压缩算法以节约内存. 所有用户的特质字符串都被存储在了一个长为n的字符串S中.(n <= 1000)用户的特质使用一个整数p表示

SPOJ 705 Distinct Substrings(后缀数组)

[题目链接] http://www.spoj.com/problems/SUBST1/ [题目大意] 给出一个串,求出不相同的子串的个数. [题解] 对原串做一遍后缀数组,按照后缀的名次进行遍历, 每个后缀对答案的贡献为n-sa[i]+1-h[i], 因为排名相邻的后缀一定是公共前缀最长的, 那么就可以有效地通过LCP去除重复计算的子串. [代码] #include <cstdio> #include <cstring> #include <algorithm> usi

hdu5769--Substring(后缀数组)

题意:求含有某个字母的某个字符串的不同子串的个数 题解:后缀数组,记录每个位置距离需要出现的字母的距离就可以了.因为不太了解后缀模版卡了一会,还是很简单的. 记住sa和height数组都是1-n的下标. //后缀数组 #include <stdio.h> #include <cstring> #include <iostream> #include <algorithm> using namespace std; typedef long long ll;

hdu 3518 Boring counting 后缀数组LCP

题目链接 题意:给定长度为n(n <= 1000)的只含小写字母的字符串,问字符串子串不重叠出现最少两次的不同子串个数; input: aaaa ababcabb aaaaaa # output 2 3 3 思路:套用后缀数组求解出sa数组和height数组,之后枚举后缀的公共前缀长度i,由于不能重叠,所以计数的是相邻height不满足LCP >= i的. 写写对后缀数组倍增算法的理解: 1.如果要sa数组对应的值也是1~n就需要在最后加上一个最小的且不出现的字符'#',里面y[]是利用sa数

【tyvj1860】后缀数组

描述 我们定义一个字符串的后缀suffix(i)表示从s[i]到s[length(s)]这段子串.后缀数组(Suffix array)SA[i]中存放着一个排列,满足suffix(sa[i])<suffix(sa[i+1]) 按照字典序方式比较定义height[i]表示suffix(sa[i])与suffix(sa[i-1])之间的最长公共前缀长度,其中height[1]=0你的任务就是求出SA和height这两个数组.字符串长度<=200000 输入格式 一行,为描述中的字符串(仅会出现小写

BZOJ 3238 AHOI 2013 差异 后缀数组+单调栈

题目大意: 思路:一看各种后缀那就是后缀数组没跑了. 求出sa,height之后就可以乱搞了.对于height数组中的一个值,height[i]来说,这个值能够作为lcp值的作用域只在左边第一个比他小的位置到右边第一个比他小的位置.这个东西很明显可以倍增RMQ+二分/单调栈. 之后就是数学题了 Σlen[Ti] + len[Tj] = (len + 1) * len * (len - 1),之后吧所有求出来的Σ2 * lcp(Ti,Tj)减掉就是答案. 记得答案开long long CODE:

hdu 5030 Rabbit&#39;s String(后缀数组&amp;二分)

Rabbit's String Time Limit: 40000/20000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 288    Accepted Submission(s): 108 Problem Description Long long ago, there lived a lot of rabbits in the forest. One day, the

hdu 4416 Good Article Good sentence(后缀数组&amp;思维)

Good Article Good sentence Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2308    Accepted Submission(s): 649 Problem Description In middle school, teachers used to encourage us to pick up pre