相似的子串--------------------------------------------思維(哈希+二分)

在這裏插入圖片描述
在這裏插入圖片描述
解析:
題目本質讓我們求解的是在主串中選出k個不相交的子串。這個子串的最長長度是多少。其實答案具有單調性,二分求解。
我們首先字符串哈希預處理,然後二分答案
判斷部分:
用兩個哈希表分別記錄長度爲len的子串位置和長度爲len的子串個數,分別記爲V和T
每次判斷長度爲len的子串,判斷與上一個記錄的位置是否合法,合法就更新V和T

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10000;
typedef unsigned long long ull;
ull P=131;
ull h[N],p[N];
char s[N];
int n,k;
unordered_map<ull,int> v,t; 
ull get(int l,int r)
{
	return h[r]-h[l]*p[r-l];
}
bool check(int len)
{
	v.clear();t.clear();
	for(int i=len;i<=n;i++)
	{
		ull m=get(i-len,i);
		if(!v[m]) v[m]=i,t[m]++;
		else if(v[m]<=i-len) v[m]=i,t[m]++;
		if(t[m]>=k) return 1;
		
	}
	return 0;
}
int main()
{
	cin>>n>>k;
	cin>>(s+1);
	p[0]=1;
	for(int i=1;i<=n;i++)
	{
		p[i]=p[i-1]*P;
		h[i]=h[i-1]*P+(s[i]-'a'+1);
	}
	int l=0,r=n/k;
	while(l<r)
	{
		int mid=l+r+1>>1;
		if(check(mid)) l=mid;
		else r=mid-1;
	 } 
	 cout<<l<<endl;
}

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