poj2774 后缀数组 公共子串

链接:http://poj.org/problem?id=2774

题意:求两个字符串的最长公共子串长度

 

第一次后缀数组,模板之。

利用后缀数组求公共子串,首先将两个字符串合并成一个字符串,两个字符串之间加上一个比字符串里所有字符都小的字符。

求出该字符串的height[]数组,当且仅当suffix[sa[i]]和suffix[sa[i-1]]不是同一个字符串的后缀数组时,求出最大的height[i],为答案。

基本定义:

s[i]表示字符串,s[i]最好不要小于0,试过换成数字算,有负数就错了

sa[i]=j表示排第i的下标是j,比如sa[2]=3,排第二的下标元素是3。

rank[i]=j表示下标是i的排第j,比如rank[3]=2,下标元素是3的排第二。sa与rank为互逆关系,即sa[rank[i]]=i。

suffix[i]表示字符串从i开始的后缀

height[i]表示suffix[sa[i]]与suffix[sa[i-1]]的最长公共子串,即排名相邻的两个数组的公共子串长度。

注意::height数组的值应该是从height[1]开始的,而且height[1]应该是等于0的。原因是,因为我们在字符串后面添加了一个0号字符,所以它必然是最小的一个后缀。

要注意height数组的范围应该是[1..n]。所以调用时应该是setheight(sa,len)而不是calheight(sa,len+1)。setheight过程中,对rank数组求值的for语句的初始语句是i=1而不是i=0的原因,和上面说的类似,因为sa[0]总是等于那个已经失去作用的0号字符,所以没必要求出其rank值。

 

#include<stdio.h>
#include<math.h>
#include<string.h>
#define N 200060
char s[N];
int len;   //数组长度
int wa[N],wv[N],height[N],wb[N],ws[N];
int rank[N],sa[N];

int cmp(int y[],int a,int b,int j)
{
	return (y[a]==y[b]&&y[a+j]==y[j+b]);
}

void setsa(int sa[],int n,int m)        //这里的n是数组长度len+1,数组末尾补了一个0
{
	int i,j,*x=wa,*y=wb,*t,p;
	//下面三个for为基数排序,按照大小与前后排序
	memset(ws,0,sizeof(ws));
	for(i=0;i<n;i++)
		ws[x[i]=s[i]]++;
	for(i=1;i<m;i++)
		ws[i]+=ws[i-1];
	for(i=n-1;i>=0;i--)   //注意是从n-1开始
		sa[--ws[x[i]]]=i;

	for(j=1,p=1;p<n;m=p,j*=2)
	{
		for(p=0,i=n-j;i<n;i++)
			y[p++]=i;
		for(i=0;i<n;i++)
			if(sa[i]>=j)
				y[p++]=sa[i]-j;
		for(i=0;i<n;i++)
			wv[i]=x[y[i]];
		//基数排序
		memset(ws,0,sizeof(ws));
		for(i=0;i<n;i++)
			ws[wv[i]]++;
		for(i=1;i<m;i++)
			ws[i]+=ws[i-1];
		for(i=n-1;i>=0;i--)
			sa[--ws[wv[i]]]=y[i];        //注意这里的下标换成y[i]
		t=x;x=y;y=t;                      //交换x和y
		for(p=1,x[sa[0]]=0,i=1;i<n;i++)
			x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?(p-1):(p++);
	}

}

void setheight(int sa[],int n)     //这里的n是数组长度len
{
	int i,j,k=0;
	for(i=1;i<=n;i++)        //求出rank,由于sa[0]是在数组上补回去的0,所以sa[0]不属于数组,所以从sa[1]开始
		rank[sa[i]]=i;
	for(i=0;i<n;height[rank[i++]]=k)
		for(k?k--:0,j=sa[rank[i]-1];s[i+k]==s[j+k];k++);
}

int main()
{
	int i,j,n,m,max;
	gets(s);
	n=strlen(s);
	s[n]='$';
	gets(s+n+1);
	len=strlen(s);
	s[len]=0;
	setsa(sa,len+1,200);       //建sa数组
	setheight(sa,len);        //建height数组
	for(i=2,max=-100000;i<=len;i++)
		if( ( (sa[i]<n&&sa[i-1]>n)||(sa[i-1]<n&&sa[i]>n) )&&height[i]>max)
			max=height[i];
	printf("%d\n",max);
	return 0;
}
Python网络爬虫与推荐算法新闻推荐平台:网络爬虫:通过Python实现新浪新闻的爬取,可爬取新闻页面上的标题、文本、图片、视频链接(保留排版) 推荐算法:权重衰减+标签推荐+区域推荐+热点推荐.zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值