YbtOJ hash和hash表课堂过关 例4 单词背诵【hash】【二分】

在这里插入图片描述

思路

首先把需要背诵的单词存入 h a s h hash hash 表。
然后我们要把单词表里的单词先扫一遍,统计出最坏长度的答案。
然后用尺取法,不断向右移动 r r r, 当当前长度已经可以得到最坏长度的答案,就更行长度,然后把l向右移到一个单词出列(遇到相同单词继续移)。
注意:单词表中的单词可能不需要背诵!

代码

#include<algorithm>
#include<iostream>
#include<cstdio>
using namespace std;
int wz[100010],t[100010],t2[100010];
unsigned long long js;
string s[100010];
int n,m,ans,ansjl;
struct node
{
    
    
	unsigned long long hash1,hash2;
	long long bj; 
}a[100010];
bool cmp(const node&df,const node&df2)
{
    
    
	return df.hash1<df2.hash1;
}
int main()
{
    
    
    cin>>n;
    for(int i=1; i<=n; i++)
     {
    
    
     	cin>>s[i];
     	a[i].bj=i;
     	int lon=s[i].size();
     	for(int j=0; j<=lon-1; j++)
     	   a[i].hash1=a[i].hash1*131ull+(s[i][j]-43);
	 }
	sort(a+1,a+1+n,cmp);
	cin>>m;
	for(int i=1; i<=m; i++)
	 {
    
    
	 	cin>>s[i];
	 	int lon=s[i].size();
	 	wz[i]=-1,js=0;   //初始化-1,如果出现主义中的状况就可直接判断
	 	for(int j=0; j<=lon-1; j++)
	 	   js=js*131ull+(s[i][j]-43);
	 	int l=1,r=n,mid=0;
	 	while(l<=r)
	 	 {
    
    
	 	 	mid=(l+r)>>1; 
	 	 	if(js<a[mid].hash1)
	 	 	  r=mid-1;
	 	 	else if(js>a[mid].hash1)
	 	 	  l=mid+1;
	 	 	else
	 	 	 {
    
    
	 	 	 	wz[i]=a[mid].bj;
	 	 	 	break;
			 }
		 }
		if(t[wz[i]]==0&&!(wz[i]==-1))
		 {
    
    
		 	t[wz[i]]=1;
		 	ans++;
		 }
	 }
	cout<<ans;
	ansjl=m;
	int l=1,ans2=0;
	for(int r=1; r<=m; r++)
	 {
    
    
	 	if(wz[r]!=-1)
	 	 {
    
    
	 	 	if(t2[wz[r]]==0)
	 	 	  ans2++;
	 	 	t2[wz[r]]++;
	 	    if(wz[l]!=-1)
	 	     {
    
    
	 	       while(l<=r&&ans2==ans)
	 	        {
    
    
	 	        	t2[wz[l]]--;
	 	        	if(t2[wz[l]]==0)
	 	        	 {
    
    
	 	        	 	ansjl=min(ansjl,r-l+1);
	 	        	 	ans2--;
					 }
					l++;
		        }
			 }	
		 }
	 }
	cout<<endl<<ansjl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Jackma_mayichao/article/details/114414836