寒假预备役总结(2.22)

这几天写了几道题

P3375 【模板】KMP - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

P3370 【模板】字符串哈希 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

P4391 [BOI2009] Radio Transmission 无线传输 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

第一个是kmp的模板题,直接套板子就行,但是这里有一个要注意的点就是,这个题中模式串里面可能有多个字串,就会有多个答案,还要输出一下next数组

下面附上代码:

#include<stdio.h>
#include<string.h>
#define N 1000010
char A[N],B[N];
int p[N];
int main()
{
    scanf("%s%s",A+1,B+1);
    int i,j=0;
    p[1]=0;
    int n=strlen(A+1),m=strlen(B+1);
    for(int i=1;i<m;i++)//构建next数组(这里是p数组)
	{
        while(j&&B[j+1]!=B[i+1])//如果不是第一个字符就不匹配,j就回退
			j=p[j];
        if(B[i+1]==B[j+1])//匹配成功j就++,循环结束i会自加
			j++;
		p[i+1]=j;//给next数组赋值
    }

    //kmp算法
    j=0;
    for(int i=0;i<n;i++)
	{
        while(j&&B[j+1]!=A[i+1])
			j=p[j];
        if(B[j+1]==A[i+1])
			j++;
        if(j==m)//匹配成功
		{
			printf("%d\n",i-strlen(B+1)+2);
			j=p[j];//下次继续匹配
		}
    }
    for(int i=1;i<=m;i++)//输出next数组
		printf("%d ",p[i]);
    return 0;
}

第二个题目时hash的模板题,我理解的哈希就是将一个字符串(大部分时用于字符串)用一个哈希值表示,这个哈希值来表示,凭此哈希值来区分字符串的不同,当然,不同的字符串的哈希值可能会相同(也就是哈希冲突),我们会尽量避免这种哈希冲突

下面附上代码:

#include<stdio.h>
#include<string.h>
#include<math.h>
#define ull unsigned long long int
#define N 10010
ull base=131;//最好是一个素数
ull a[N];//存放字符串的哈希值
char s[N];
ull hash(char s[])//返回一个字符串的哈希值res
{
	int len=strlen(s);
	ull res=0;
	for(int i=0;i<len;i++)
		res=(res*base+(ull)s[i])%(ull)pow(2,32);
	return res;
}
void qsort(int l,int r)//快排函数
{
	ull temp=a[(l+r)/2];
	int i=l,j=r;
	while(1)
	{
		if(i>=j)
			break;
		while(a[j]>temp)
			j--;
		while(a[i]<temp)
			i++;
		if(i<=j)
		{
			ull temp1=a[i];
			a[i]=a[j];
			a[j]=temp1;
			i++;
			j--;
		}
	}
	if(j>l)
		qsort(l,j);
	if(i<r)
		qsort(i,r);
}
int main()
{
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%s",s);
		a[i]=hash(s);
	}
	qsort(1,n);
//	for(int i=1;i<=n;i++)
//		printf("%d ",a[i]);
//	printf("\n");
	int sum=1;
	for(int i=1;i<n;i++)
		if(a[i]!=a[i+1])
			sum++;
	printf("%d",sum);
	return 0;
}

第三题时一个对kmp算法中的next数组理解有很大帮助的一个题目,写完后你会发现对next数组的理解又深一点,利用next数组来求出最短重复序列的长度,next[x]=0,next[x+1]=1,next[x+2]=2,....其中x就是最短重复序列的值,这个规律应该很容易就能理解,根据此规律就能求出最短重复序列的长度x=n-next[n-1],n为串的长度(next[i]记录的就是i前面的前缀和后缀的最长重复长度)

下面附上代码:

#include<stdio.h>
#define N 1000010
int l;
char s1[N];
int next[N];
int main()
{
	scanf("%d%s",&l,s1);
	next[0]=0;
	int j=0;
	for(int i=1;i<l;i++)
	{
		while(j&&s1[i]!=s1[j])
			j=next[j-1];
		if(s1[i]==s1[j])
			j++;
		next[i]=j;
	}
// 	for(int i=0;i<l;i++)
// 		printf("%d ",next[i]);
	printf("%d",l-next[l-1]);//可以自己推导试试
	return 0;
}

  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值