Шаблоны молока POJ (массив суффиксов и дихотомия)

Этот вопрос в основном тот же, что и в Музыкальной теме, которую я написал вчера . В этом блоге есть исследование массива суффиксов. Если вы не писали этот вопрос раньше, вы можете сделать это после того, как закончите.

заглавие

Очевидно, что нужно найти длину самой длинной повторяемой подстроки, но количество повторов подстроки не должно быть меньше K.

Идеи

Луо Суйцянь «Массив суффиксов - мощный инструмент для обработки строк»
сначала находит группу дерева суффиксов, а затем использует группу дерева суффиксов, чтобы найти массив высот (height [i]: сохраняет самый длинный повторяющийся префикс подстрок суффиксов, ранжированных i и i-1 Длина подстроки). Разделите отсортированные суффиксы на несколько групп, где значение высоты между суффиксами каждой группы не меньше k. Например, строка "aabaaaab", когда k = 2, суффикс делится на 4 группы, как показано на рисунке.
Можно представить, что когда высота в группе не меньше k, нам нужно только оценить количество массивов суффиксов, содержащихся в группе. Достаточно ли оно не меньше K, если оно выполняется, тогда, когда длина равна k, условие также выполняется, поэтому нам нужно разделить длину на два, а затем судить, возможно ли это.

Код
#pragma GCC optimize(2)
//#include<bits/stdc++.h>
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;

typedef long long ll;
typedef unsigned long ul;
typedef unsigned long long ull;
#define pi acos(-1.0)
#define e exp(1.0)
#define pb push_back
#define mk make_pair
#define fir first
#define sec second
#define scf scanf
#define prf printf
typedef pair<ll,ll> pa;
const ll INF=0x3f3f3f3f3f3f3f3f;
const ll maxn=2e4+7;
const ll maxnum=1e6+7;
ll N,M,K;
ll sa[maxn],rank[maxn],r[maxn],height[maxn],tmp[maxn]; 
bool cmp(ll i,ll j){
    
    
	if(rank[i]!=rank[j])
	return rank[i]<rank[j];
	ll r1=i+K<=N?rank[i+K]:-1;
	ll r2=j+K<=N?rank[j+K]:-1;
	return r1<r2;
}
//求后缀数组 
void do_sa(){
    
    
	ll i,j;
	for(i=0;i<=N;i++){
    
    
		sa[i]=i;
		rank[sa[i]]=(i!=N?r[i]:-1);
	}
	for(K=1;K<=N;K<<=1){
    
    
		sort(sa,sa+1+N,cmp);
		tmp[sa[0]]=0;
		for(i=1;i<=N;i++)
		tmp[sa[i]]=tmp[sa[i-1]]+(cmp(sa[i-1],sa[i])?1:0);
		for(i=0;i<=N;i++)
		rank[i]=tmp[i];
	}
	return ;
}
void get_height(){
    
    
	ll i,j,k=0;
	//枚举每个后缀的起始位置 
	for(i=0;i<N;i++){
    
    
		if(k)
		k--;
		else
		k=0;
		j=sa[rank[i]-1];
		while(r[i+k]==r[j+k])
		k++;
		height[rank[i]]=k;//height[i]:存储排名为i和i-1的后缀子串的最长前缀子串长度 
	}
	return ;
	
}
bool check(ll mid){
    
    
	ll i,j,cnt=0;
	for(i=1;i<=N;i++){
    
    
		if(height[i]>=mid){
    
    
			cnt++;
			if(cnt+1>=M)
			return true;
		}
		else
		cnt=0;
	}
	return false;
}
int main()
{
    
    
//  freopen(".../.txt","w",stdout);
//  freopen(".../.txt","r",stdin);
	ios::sync_with_stdio(false);
	ll i,j,k;
	cin>>N>>M;
	for(i=0;i<N;i++)
	cin>>r[i];
	do_sa();
	get_height();
	ll L=0,R=N,mid,res=0;
	while(L<=R){
    
    
		mid=(R-L)/2+L;
		if(check(mid)){
    
    
			L=mid+1;
			res=max(res,mid);
		} 
		else{
    
    
			R=mid-1;
		}
	}
	cout<<res<<endl;
	return 0;
}

рекомендация

отblog.csdn.net/weixin_43311695/article/details/107656420