/* 手打的哈希+线性的维护 第一问:hash一下 并且用个h记录某个单词要背的 第二问:线性的跑一边 开始队列里装下前一些单词使这一坨符合要求 并且记录出现次数num 然后开始从前面删 删除的条件:要么是非法的单词(h值为0) 要么num值大于1 如果删不了就在进来一个 更新num 直到跑完 这过程中每次更新l 注意这样有极端数据 如果第一问答案为 0 需要特判一下 */ #include<iostream> #include<cstdio> #include<cstring> #include<map> #define maxm 100100 #define maxn 100010 #define mod 100007 #define p 17 using namespace std; char s[maxn][12],ss[maxn][12]; int n,m,f[maxn],a[maxm],ans,l=maxn; int h[maxn],num[maxn],vis[maxn],head,tail; int get_hash(char *str) { int len=strlen(str),hash=0; for(int i=0;i<=len-1;i++) hash=(hash*p+str[i]-‘a‘)%mod; return hash; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%s",s[i]); scanf("%d",&m); for(int i=1;i<=m;i++) { scanf("%s",ss[i]); f[get_hash(ss[i])]=1; } for(int i=1;i<=n;i++) { int tmp=get_hash(s[i]); if(f[tmp]==1) { ans++; h[tmp]=1; } } int si=0; head++; while(tail<=m) { int tmp=get_hash(ss[++tail]); if(h[tmp]) { if(vis[tmp]==0) si++; num[tmp]++; vis[tmp]=1; } if(si==ans&&si!=0) { int x=get_hash(ss[head]); while(head<tail&&(h[x]==0||num[x]>1)) { if(h[x]) num[x]--; x=get_hash(ss[++head]); } l=min(l,tail-head+1); } } if(ans)printf("%d\n%d\n",ans,l); else printf("0\n0"); }
时间: 2024-10-08 20:01:50