10pts玄关求调,只过了#8,感谢
  • 板块P1381 单词背诵
  • 楼主Ryoo
  • 当前回复0
  • 已保存回复0
  • 发布时间2024/11/24 11:56
  • 上次更新2024/11/24 14:36:14
查看原帖
10pts玄关求调,只过了#8,感谢
1100140
Ryoo楼主2024/11/24 11:56
#include <bits/stdc++.h>
using namespace std;
bool flag[1005], pdflag[1005];
int len;
int n,m;
//存储文章的结构体
struct dia{
	int type;
	char words[11];
	unsigned long long ha;
}posts[100005];
//存储要背带单词的数组
struct word{
	char words[11];
	unsigned long long ha;
	//node *pots = new node(),*tail;
	//int lon = 0;
}a[1005];

bool cmp(word x,word y) {
	return x.ha < y.ha;
}

unsigned long long hash1(char *x) {
	int len = strlen(x);
	unsigned long long ha = 0;
	for(int i = 0; i < len; i++) {
		ha = ha*131+(x[i]-'a'+1);
	}
	return ha;
}
//二分答案确定序列左侧的最大值
int binary_l(int x, int y) {
	int mid = (x+y+1)/2;
	while(x < y) {
		//二分答案
		for(int i = mid; i <= m; i++) {
			pdflag[posts[i].type] = 1;
		}
		int pd = 1;
		for(int i = 1; i <= 1000; i++) {
			if(flag[i] != pdflag[i]) pd = 0;
		}
		memset(pdflag, 0, sizeof(pdflag));
		if(pd) {x = mid;mid = (x+y+1)/2;}
		else {y = mid-1;mid = (x+y+1)/2;}
	}
	return x;
}
//二分答案确定序列右侧的最小值
int binary_r(int x, int y) {
	int mid = (x+y)/2;
	while(x < y) {
		for(int i = 1; i <= mid; i++) {
			pdflag[posts[i].type] = 1;
		}
		int pd = 1;
		for(int i = 1; i <= 1000; i++) {
			if(flag[i] != pdflag[i]) pd = 0;
		}
		memset(pdflag, 0, sizeof(pdflag));
		if(pd) {y = mid;mid = (x+y)/2;}
		else {x = mid+1;mid = (x+y)/2;}
	}
	return x;
}
//二分查找,用于匹配文章中的单词与要背的单词
int binary_1(int x, int y, unsigned long long has) {
	int mid = (x+y)/2;
	while(x <= y) {
		if(a[mid].ha > has) {y = mid;mid = (x+y)/2;}
		else if(a[mid].ha < has){x = mid+1;mid = (x+y)/2;} 
		else {return mid;}
	}
	return -1;
}
int main() {	
	scanf("%d", &n);
	//预处理要背的单词的hash值
	for(int i = 1; i <= n; i++) {
		scanf("%s", a[i].words);
		a[i].ha = hash1(a[i].words);
	}
	//以hash值大小为依据给a数组排序
	sort(a+1, a+1+n, cmp);
	scanf("%d", &m);
	//预处理文章中每个单词的hash值和属于哪种类型的单词
	for(int i =1; i <= m; i++) {
		scanf("%s", posts[i].words);
		posts[i].ha = hash1(posts[i].words);
		
		posts[i].type = binary_1(1,n,posts[i].ha);
		if(!flag[posts[i].type] && posts[i].type != -1) len++;
		flag[posts[i].type] = 1;
	}
	int l = 1, r = m;	//l,r为最短序列的首尾坐标
	l = binary_l(l,r);
	r = binary_r(l,r);
	if(len == 0) {		//特判
		printf("0 0");
		return 0;
	}
	printf("%d\n%d", len, r-l+1);
	return 0;
	
}

在讨论区看到的一组数据也过了

/*
input:
6
cyq
lyw
ak
ioi
wuweiqi
linmeng
15
linmeng
ak
ioi
cyq
ak
ioi
lyw
ak
ioi
wuweiqi
ak
ioi
cyq
ak
lyw
output:
6
10
*/
2024/11/24 11:56
加载中...