Luogu-1381 单词背诵

先将n个单词插入哈希表,记录左右端点,每次右端点往后移动,读入一个新的单词并记录下它的哈希值,如果这个单词之前没出现过那么更新(ans)(minl),如果左端点的单词出现了不止一次则可以往右缩,从而保证长度最短。

#include<map>
#include<cmath>
#include<ctime>
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline int read(){
	int ans=0,fh=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-')
			fh=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9')
		ans=(ans<<1)+(ans<<3)+ch-'0',ch=getchar();
	return ans*fh;
}
typedef long long ll;
typedef unsigned long long ull;
const int maxn=1e5+100,maxm=1e3+100;
const ull base=131,P=1e6+3;
struct hash{
	int siz[P],cz[P];
	inline ull gethash(char *s){
		ull ans=0;
		for(int i=0,L=strlen(s);i<L;i++)
			ans=(ans*base+s[i])%P;
		return ans;
	}
//	inline void revise(char *s,int z){
//		ull x=gethash(s);
//		siz[x]+=z;
//	}
	inline void insert(char *s){
		ull x=gethash(s);
		cz[x]=1;
	}
//	inline int query(char *s){
//		ull x=gethash(x);
//		return siz[x];
//	}
	inline int find(char *s){
		ull x=gethash(s);
		if(!cz[x]) x=-1;
		return x;
	}
}h;
int n,a[maxn],m,ans,minl;
char s[maxm];
int main(){
	//freopen(".in","r",stdin);
	//freopen(".out","w",stdout);
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%s",s),h.insert(s);
	scanf("%d",&m);
	int l=0;
	for(int i=1;i<=m;i++){
		scanf("%s",s);
		int x=h.find(s);
		a[i]=x;
		if(~x){
			if(h.siz[x]==0) ans++,minl=i-l;
			h.siz[x]++;
			while(a[l+1]==-1||h.siz[a[l+1]]>1)
				l++,h.siz[a[l]]--,minl=min(minl,i-l);
		}
	}
	printf("%d
%d
",ans,minl);
	return 0;
}
原文地址:https://www.cnblogs.com/nianheng/p/9922569.html