P1381 單詞背誦(hash+隊列)

題目描述
靈夢有n個單詞想要背,但她想通過一篇文章中的一段來記住這些單詞。

文章由m個單詞構成,她想在文章中找出連續的一段,其中包含最多的她想要背的單詞(重複的只算一個)。並且在背誦的單詞量儘量多的情況下,還要使選出的文章段落儘量短,這樣她就可以用盡量短的時間學習儘可能多的單詞了。

輸入格式
第1行一個數n,

接下來n行每行是一個長度不超過10的字符串,表示一個要背的單詞。

接着是一個數m,

然後是m行長度不超過10的字符串,每個表示文章中的一個單詞。

輸出格式
輸出文件共2行。第1行爲文章中最多包含的要背的單詞數,第2行表示在文章中包含最多要背單詞的最短的連續段的長度。
輸入:
3
hot
dog
milk
5
hot
dog
dog
milk
hot
輸出:
3
3
說明/提示
【數據範圍】

對於30%的數據 n<=50,m<=500;

對於60%的數據 n<=300,m<=5000;

對於100%的數據 n<=1000,m<=100000;
中文題目不解釋題意~
思路:

  1. 字符串匹配直接想到hash,用hash完全可以解決第一個問題;
  2. 本題的關鍵在第二問,找最短的含有最大單詞數的連續段長度;暴力沒想到怎麼暴力,然後想到可以用尺取,滑動尋找,但是寫了半天wa了一發,自己找到反例,應該是尺取的本事還沒到家~~
  3. 後來看到有用隊列A的,瞬間又有了思路,所有解釋都在無敵詳細的註釋中!!!
    代碼:
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define H 0x7FFFFFFF
using namespace std;
const int maxn=1e5+7;
const ll INF=1e9+7;
char s[20];
map<ull,int>mp;
ull gethash(char *a)
{
	ull sum=0;
	for(int i=0;a[i]!='\0';i++)
	{
		sum=sum*131+a[i];
	}
	return sum&H;
}
map<ull,int>mp2;
char a[maxn][15];
int main()
{
	ll n,m;
	scanf("%lld",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%s",s);
		mp[gethash(s)]=1;
	}
	scanf("%lld",&m);
	ll num=0;
	for(int i=1;i<=m;i++)
	{
		scanf("%s",a[i]);
		ull x=gethash(a[i]);
		if(mp[x]==1)            //hash解決第一問
		{
			num++;
			mp[x]++;
		}
	}
	printf("%lld\n",num);
	queue<int>q;
	bool flag=false;
	ll ans=INF;
	for(int i=1;i<=m;i++)
	{
		if(mp[gethash(a[i])]==0)
            mp2[gethash(a[i])]=INF;
        /*
            這裏要將文章中出現的但不需要背的賦爲最大,順着往後理解就能懂
            否則過不了下面註釋的例子
            因爲這裏卡了很久
        */
		flag=false;					//不要忘了初始化
		if(!mp2[gethash(a[i])])
			flag=true;
        /*
            這裏當該單詞需要背,並且文章中沒有出現過時,ans爲隊列長度;否則爲ans與隊列長度取最小;
            取最小是因爲隊首元素可能會被去掉,在下面的操作中
            這裏要分開討論的原因爲這個例子:3 a b c 5 a b a a a ;這樣處理後面的三個a就不會被計算
        */
		q.push(i);
		mp2[gethash(a[i])]++;
		int k=q.front();
		while(mp2[gethash(a[k])]>1&&q.size())    //當隊首元素出現過>1次時,  去掉該元素;
		{
			mp2[gethash(a[k])]--;
			q.pop();
			k=q.front();
		}
		ll t=q.size();
		if(flag)
			ans=t;
		else
		ans=min(t,ans);
	}
	printf("%lld\n",ans);
	return 0;
}
/*
3
a
b
c
5
a
b
e
a
a
*/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章