[SNOI2020] String (suffix array SA + and search set)

Title

Insert picture description here

answer

It is rare to find the solution of the suffix array that can be seen on the Internet, so I will write an article.

We found that this question is compatible with suffix arrays. Separate the two strings with special symbols to process SA and h. Then the cost of matching two substrings is m minus their lcp length, and lcp is two strings The minimum value of the interval on the h array.

These are the most common usages of SA. It can be said that this question was born for SA.

What to do next?

Think greedily, we can try to pair the two strings with the length of lcp first, and the strings with the
longer lcp, then they should be relatively close to each other in SA, summarize the four points, and then analogize. Prove or understand this greedy idea well, so there must be no better solution for matching. I will not draw a diagram to prove it here. It is not necessary.

So it is a common operation of SA: and check set

Start the merger from the largest h, and count the contribution during the merger.

See the code for details

CODE

#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 300005
#define MAXC 26
#define LB 'a'
#define LL long long
#define DB double
#define ENDL putchar('\n')
LL read() {
    
    
	LL f = 1,x = 0;char s = getchar();
	while(s < '0' || s > '9') {
    
    if(s=='-')f = -f;s = getchar();}
	while(s >= '0' && s <= '9') {
    
    x=x*10+(s-'0');s = getchar();}
	return x * f;
}
const int MOD = 1000000007;
int n,m,i,j,s,o,k;
char ss[MAXN];
int a[MAXN];
int sa[MAXN],rk[MAXN],ht[MAXN],h[MAXN];
int rt[MAXN],nx[MAXN],tl[MAXN],pr[MAXN<<1];
int ins(int i,int x,int y) {
    
    return x==0 ? (rt[i]=y):(nx[x]=y);}
void INIT_SUFFIX_ARRAY(char *s,int *sa,int *rk,int n) {
    
    
	for(int i=1;i<=n;i++)sa[i]=rk[i]=rt[i]=nx[i]=tl[i]=pr[n+i]=0;
	for(int i = 1;i <= n;i ++) 
		nx[tl[0+s[i]] = ins(0+s[i],tl[0+s[i]],i)] = 0;
	int cn = 0,nm = 0;
	for(int i = 0;i <= 256;i ++) {
    
    
		int p = rt[i];if(p) nm ++;
		while(p) {
    
    
			sa[++ cn] = p; rk[p] = nm;
			if(p == tl[i]) break;
			p = nx[p];
		} rt[i] = tl[i] = 0;
	}
	for(int ii = 1;ii <= n;ii <<= 1) {
    
    
		for(int i = 1;i <= n;i ++) pr[i] = rk[i],rk[i] = 0;
		for(int i = n-ii+1;i <= n;i ++)
			nx[tl[pr[i]] = ins(pr[i],tl[pr[i]],i)] = 0;
		for(int i = 1;i <= n;i ++) {
    
    
			if(sa[i] <= ii) continue;
			nx[tl[pr[sa[i]-ii]] = ins(pr[sa[i]-ii],tl[pr[sa[i]-ii]],sa[i]-ii)] = 0;
		}
		cn = 0;nm = 0;
		for(int i = 1;i <= n;i ++) {
    
    
			int p = rt[i],pp = 0;
			while(p) {
    
    
				sa[++ cn] = p;
				rk[p] = ((!pp || pr[p+ii] != pr[pp+ii]) ? (++nm):nm);
				if(p == tl[i]) break;
				pp = p;p = nx[p];
			} rt[i] = tl[i] = 0;
		}
	}
	return ;
}
void INIT_HEIGHT(char *s,int *sa,int *rk,int *hi,int n) {
    
    
	hi[0] = 0;
	for(int i = 1;i <= n;i ++) {
    
    
		int k = sa[rk[i]-1];if(!k) {
    
    hi[i]=0;continue;}
		hi[i] = max(hi[i-1]-1,0);
		while(s[k+hi[i]] == s[i+hi[i]]) hi[i] ++;
	}
	return ;
}
int fa[MAXN],ct[MAXN];
int Abs(int x) {
    
    return x<0 ? -x:x;}
int findf(int x) {
    
    return x==fa[x] ? x:(fa[x] = findf(fa[x]));}
int unionSet(int a,int b) {
    
    
	int u = findf(a),v = findf(b),re = 0;
	if(ct[u]*1ll*ct[v] > 0) re = 0;
	else re = min(Abs(ct[u]),Abs(ct[v]));
	ct[v] = ct[u] + ct[v];
	fa[u] = v; return re;
}
vector<int> c[MAXN];
int main() {
    
    
	n = read();m = read();
	scanf("%s",ss + 1);
	ss[n+1] = '#';
	scanf("%s",ss + n + 2);
	int N = (n<<1|1);
	INIT_SUFFIX_ARRAY(ss,sa,rk,N);
	INIT_HEIGHT(ss,sa,rk,ht,N);
	for(int i = 1;i <= N;i ++) h[i] = ht[sa[i]];
	for(int i = 1;i <= N;i ++) {
    
    
		fa[i] = i;ct[i] = 0;
		if(sa[i] <= n-m+1) ct[i] = 1;
		else if(sa[i] > n+1 && sa[i] <= N-m+1) ct[i] = -1;
		if(i-1) c[h[i]].push_back(i);
	}
	LL ans = (n-m+1) *1ll* m;
	for(int i = n;i >= 0;i --) {
    
    
		for(int j = 0;j < (int)c[i].size();j ++) {
    
    
			int t = c[i][j];
			ans -= unionSet(t-1,t) *1ll* (min(i,m));
		}
	}
	printf("%lld\n",ans);
	return 0;
}

Guess you like

Origin blog.csdn.net/weixin_43960414/article/details/112578740