Suffix Array Special _ACM

Source: Internet
Author: User
Tags first string new set stdin cmath

6 Topic Links: Click to open the link

(This is the problem of personal AC for the training questions of the suffix array, and the problems of informal teaching are for reference only.) )

(the suffix array has a specific solution in the introductory Classic training guide for algorithmic contests, and this part of the code is fully based on the code in this book as a template)

Understanding:

A, find the length of the oldest string that repeats at least two times in a string but does not overlap

B, the length of the oldest string that repeats at least k times in a string, but can overlap, appears

C, to find the length of the longest common substring in two strings

D, to find the total number of common substrings with length greater than or equal to K in two strings

E, find the longest common substring in at least half of the string of n strings and output, if there are more than one sort

F, for a string of length n, cut two knives into three paragraphs, each flip, so that the overall dictionary order is the smallest, ask two knives where to cut, and output processing after the string.

Suggested to do the order of title:

1, F, only need to use the SA array

2, B, first find the SA array, and then the height of the array, and finally traverse the height of the array (two points)

3, A, first the SA array, and then the height of the array, and finally traverse the height of the array (two points)

4, C, the two string concatenation into a string, and then the SA array, and then the height of the array, and finally traverse the height of the array (two points)

5, E, the n string into a string, the first two to find the longest length, and then press this length to find the matching string output (two points)

6, D (difficult)


Detailed solving

Topic: F

Topic Description: For a string of length n, cut two knives into three paragraphs, each flip, so that the overall dictionary order is the smallest, ask two knives where to cut, and output processing after the string.

Practice Analysis:

For a sequence of 10 1 2 3 4, cut two knives so that the overall minimum can be so cut 10 1 | 2 | 3 4, so 10 1 in reverse order is 1 10, 2 is in reverse order 2, 3 4 is in reverse order 4 3. In fact, these two knives we can across, we can be seen as the first knife for the main sorting criteria, the second knife for the secondary sorting criteria, the first knife cut better than the first knife not cut better, so the overall optimal can be converted to local optimal, if you want to make the first paragraph after the smallest, You can consider constructing the suffix array sa after the entire string is in reverse order, then sa "0" refers to the starting point of a string that can be minimized after a reverse order, i.e. SA "0" is the position of the first knife. Taking the above sequence as an example, the overall string is reversed to 4 3 2 1 10, then the position of SA "0" is in 1, because 1 10 is the smallest, so the first knife is cut before 1. Next, we'll cut the second knife in 4 3 2, so we'll do another suffix array for the 4 3 2 sequence, get the new SA array, and get the second knife position from SA "0".

Through the above analysis, this cut two knives divided into three sections of the problem can be extended to cut n knife points n+1 section of the problem. There are also a few details to be noted, because at least 2 knives are divided into 3 sections, so the first knife is not necessarily sa "0", such as the sa "0" position is the last one of the sequence, then the second knife can only cut the air, so to add a judge sa "0" is not the case of SA "1" does not line SA "2", Find the proper position of the first knife to cut the position of the second knife.


Code Show:

#include <iostream> #include <cstring> #include <algorithm> #include <cmath> using namespace std
;
const int maxn=200010;
int O[MAXN],S[MAXN],SA[MAXN],T[MAXN],T2[MAXN],C[MAXN];
	struct node {int val,pos;
	BOOL operator < (const node & x) const {return val<x.val;
}} TMP[MAXN];
	void Build_sa (int n,int m) {int i,*x=t,*y=t2;
	Initialize Cardinal order for (i=0; i<m; i++) c[i]=0;
	For (i=0 i<n; ++i) ++c[X[i]=s[i]];
	for (I=1; i<m; ++i) c[i]+=c[i-1];
	for (i=n-1; i>=0;-i) sa[--c[x[i]]]=i;
		Multiply cardinal order for (int k=1; k<=n; k<<=1) {int = =;
		First, the second keyword is sorted directly according to the SA Array (i=n-k; i<n; ++i) y[p++]=i;
		For (i=0 i<n; ++i) if (sa[i]>=k) y[p++]=sa[i]-k;
		Reorder the first keywords for (i=0; i<m; i++) c[i]=0;
		For (i=0 i<n; ++i) ++c[x[y[i]];
		for (I=1; i<m; ++i) c[i]+=c[i-1];
		for (i=n-1; i>=0;-i) sa[--c[x[y[i]]]]=y[i];
		reconstructs the x Array Swap (X,Y) based on the SA array;
		P=1;
		x[sa[0]]=0; For (I=1 i<n; ++i) x[sa[i]]= Y[sa[i-1]]==y[sa[i]];& Y[sa[i-1]+k]==y[sa[i]+k]?
		p-1:p++;
		if (p>=n) break;
	M=p;
	int main () {//freopen ("Datain.txt", "R", stdin);
	Ios::sync_with_stdio (FALSE);
	Cin.tie (0);
	Read int n;
	cin>>n; 			for (int i=0; i<n; ++i) {cin>>o[i];	Keep a starting value in the O array tmp[i].val=o[i];
	The TMP array is used to sort tmp[i].pos=i;
	//Sort and assign the rank, the same rank of the same result sort (tmp,tmp+n);
	s[tmp[0].pos]=0;
		for (int i=1; i<n; ++i) {if (O[tmp[i].pos]==o[tmp[i-1].pos)) S[tmp[i].pos]=s[tmp[i-1].pos];
	else s[tmp[i].pos]=i;
	//reverse order for (int i=0; i<= (n-1)/2; i++) swap (s[i],s[n-1-i));
	First to find a cutting point Build_sa (n,n);
	int first=0;
	while (sa[first]<=1) first++;
	int Ans1=n-1-sa[first];
	First=sa[first];
	Then find a second cut point Build_sa (First,n);
	int second=0;
	while (sa[second]<=0) second++;
	int Ans2=n-1-sa[second];
	Output for (int i=ans1; i>=0; i--) cout<<o[i]<<endl;
	for (int i=ans2; i>ans1; i--) cout<<o[i]<<endl;
for (int i=n-1; i>ans2; i--) cout<<o[i]<<endl; }

Topic: B

Topic Description: Find the length of the oldest string that repeats at least k times in a string but can overlap

Practice Analysis:

Constructs the suffix array sa, constructs the height array, the binary traversal length L, each time divides the height array, guarantees each paragraph the height value is not less than L, if this paragraph number of strings is greater than equals K, then the current L is eligible.

Code Show:

#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <
Cmath> using namespace std;
const int maxn=20005;
int S[MAXN];
int T[MAXN],T2[MAXN],SA[MAXN],C[MAXN];
	void Build_sa (int n,int m) {int i,*x=t,*y=t2;
	Initializes the base order for (i=0;i<m;i++) c[i]=0;
	for (I=0;i<n;++i) ++c[X[i]=s[i]];
	for (I=1;i<m;++i) c[i]+=c[i-1];
	for (i=n-1;i>=0;--i) sa[--c[x[i]]]=i;
		Multiply cardinal order for (int k=1;k<=n;k<<=1) {int = =;
		First, the second keyword for (i=n-k;i<n;++i) y[p++]=i is sorted according to the SA array directly;
		for (I=0;i<n;++i) if (sa[i]>=k) y[p++]=sa[i]-k;
		Reorder the first keyword for (i=0;i<m;i++) c[i]=0;
		for (I=0;i<n;++i) ++c[x[y[i]];
		for (I=1;i<m;++i) c[i]+=c[i-1];
		for (I=n-1;i>=0;--i) Sa[--c[x[y[i]]]]=y[i];
		reconstructs the x Array Swap (X,Y) based on the SA array;
		p=1;x[sa[0]]=0; for (I=1;i<n;++i) x[sa[i]]= Y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+k]==y[sa[i]+k]?
		p-1:p++;
		if (p>=n) break; 
	M=p;
} int RANK[MAXN],HEIGHT[MAXN]; void GetHeight (iNT N) {int k=0;
	for (int i=0;i<n;++i) rank[sa[i]]=i;
		for (int i=0;i<n;++i) {if (k) k--;
			if (Rank[i]) {int j=sa[rank[i]-1];
		while (S[i+k]==s[j+k]) k++;
	} height[rank[i]]=k;
     } bool Judge (int n,int x,int k) {int num=1,maxnum=1;
        	for (int i=1;i<n;i++) {if (height[i]<x) {num=1;
         Continue
         } num++;
         Maxnum=max (Maxnum,num);
     if (maxnum>=k) return true;    
return false;
	int main () {//Freopen ("Datain.txt", "R", stdin);
	int n,k;
		while (~SCANF ("%d%d", &n,&k)) {//read for (int i=0;i<n;++i) scanf ("%d", &s[i]);
		Constructs the SA and the Height array build_sa (n,n);
		GetHeight (n);
		Second Division find the largest length int l=0,r=n,mid=1,ans=0;
			while (l<=r) {mid= (l+r)/2;
				if (judge (N,mid,k)) {ans=mid;
			l=mid+1;
		else r=mid-1;  
	printf ("%d\n", ans);  }
}



Topic: A

Topic Description: Find the length of the oldest string that repeats at least two times in a string but does not overlap

Practice Analysis:

Constructs the suffix array sa, constructs the height array, the binary traversal length L, each time divides the height array, guarantees each paragraph the height value is not less than L, if in this paragraph existence two strings does not overlap, then the current L is qualified. It should be noted that there is a particular requirement in the topic that if the whole string plus one number equals another string, the two strings are considered equal, so a preprocessing

for (int i=0;i<n-1;++i) s[i]=s[i+1]-s[i]+89;

Code Show:

#include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std;
const int maxn=20005;
int S[MAXN];
int T[MAXN],T2[MAXN],SA[MAXN],C[MAXN];
	void Build_sa (int n,int m) {int i,*x=t,*y=t2;
	Initializes the base order for (i=0;i<m;i++) c[i]=0;
	for (I=0;i<n;++i) ++c[X[i]=s[i]];
	for (I=1;i<m;++i) c[i]+=c[i-1];
	for (i=n-1;i>=0;--i) sa[--c[x[i]]]=i;
		Multiply cardinal order for (int k=1;k<=n;k<<=1) {int = =;
		First, the second keyword for (i=n-k;i<n;++i) y[p++]=i is sorted according to the SA array directly;
		for (I=0;i<n;++i) if (sa[i]>=k) y[p++]=sa[i]-k;
		Reorder the first keyword for (i=0;i<m;i++) c[i]=0;
		for (I=0;i<n;++i) ++c[x[y[i]];
		for (I=1;i<m;++i) c[i]+=c[i-1];
		for (I=n-1;i>=0;--i) Sa[--c[x[y[i]]]]=y[i];
		reconstructs the x Array Swap (X,Y) based on the SA array;
		p=1;x[sa[0]]=0; for (I=1;i<n;++i) x[sa[i]]= Y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+k]==y[sa[i]+k]?
		p-1:p++;
		if (p>=n) break; 
	M=p;
} int RANK[MAXN],HEIGHT[MAXN];
	void getheight (int n) {int k=0; for (int I=0;i<n;++i) rank[sa[i]]=i;
		for (int i=0;i<n;++i) {if (k) k--;
			if (Rank[i]) {int j=sa[rank[i]-1];
		while (S[i+k]==s[j+k]) k++;
	} height[rank[i]]=k;
     } bool Judge (int n,int x) {int mini=sa[0],maxi=sa[0];
            for (int i=1;i<n;i++) {if (height[i]<x) {mini=sa[i];
        	Maxi=sa[i];
         Continue
         } mini=min (Mini,sa[i]);
         Maxi=max (Maxi,sa[i]);
     if (maxi-mini>x) return true;    
return false;
	int main () {//Freopen ("Datain.txt", "R", stdin);
	int n;
		while (scanf ("%d", &n) ==1 && N) {//read for (int i=0;i<n;++i) scanf ("%d", &s[i]);
		preprocessing for (int i=0;i<n-1;++i) s[i]=s[i+1]-s[i]+89;
		Construct array Build_sa (N,200);
		GetHeight (n);
		Second-division int l=0,r=n,mid=1,ans=0;
			while (l<=r) {mid= (l+r)/2;
				if (judge (N,mid)) {l=mid+1;
			Ans=mid;
		else r=mid-1;
		//Output if (ans<4) printf ("%d\n", 0);
	else printf ("%d\n", ans+1);  }
}


Topic: C

Topic Description: Find the length of the longest common substring in a two string

Practice Analysis: Stitch two strings into a string, then ask the SA array, then the height array, and finally traverse the height array (two points)

Code Show:

#include <iostream> #include <algorithm> #include <cmath> using namespace std;
const int maxn=200010;
int S[MAXN];
int T[MAXN],T2[MAXN],SA[MAXN],C[MAXN];
int len1;
	void Build_sa (int n,int m) {int i,*x=t,*y=t2;
	Initializes the base order for (i=0;i<m;i++) c[i]=0;
	for (I=0;i<n;++i) ++c[X[i]=s[i]];
	for (I=1;i<m;++i) c[i]+=c[i-1];
	for (i=n-1;i>=0;--i) sa[--c[x[i]]]=i;
		Multiply cardinal order for (int k=1;k<=n;k<<=1) {int = =;
		First, the second keyword for (i=n-k;i<n;++i) y[p++]=i is sorted according to the SA array directly;
		for (I=0;i<n;++i) if (sa[i]>=k) y[p++]=sa[i]-k;
		Reorder the first keyword for (i=0;i<m;i++) c[i]=0;
		for (I=0;i<n;++i) ++c[x[y[i]];
		for (I=1;i<m;++i) c[i]+=c[i-1];
		for (I=n-1;i>=0;--i) Sa[--c[x[y[i]]]]=y[i];
		reconstructs the x Array Swap (X,Y) based on the SA array;
		p=1;x[sa[0]]=0; for (I=1;i<n;++i) x[sa[i]]= Y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+k]==y[sa[i]+k]?
		p-1:p++;
		if (p>=n) break; 
	M=p;
} int RANK[MAXN],HEIGHT[MAXN];
	void getheight (int n) {int k=0; for (int i=0;i<n;++i) rank[sa[i]]=i;
		for (int i=0;i<n;++i) {if (k) k--;
			if (Rank[i]) {int j=sa[rank[i]-1];
		while (S[i+k]==s[j+k]) k++;
	} height[rank[i]]=k;
     } bool Judge (int n,int x) {int l=sa[0],r=sa[0];
         	for (int i=1;i<n;i++) {if (height[i]<x) {l=sa[i];
        	R=sa[i];
         Continue
         } l=min (L,sa[i]); 
         R=max (R,sa[i]);
     if (l<len1 && r>=len1) return true;    
return false;
	int main () {//Freopen ("Datain.txt", "R", stdin);
	Ios::sync_with_stdio (FALSE);
	Cin.tie (0);
	Read into string s1,s2;
	cin>>s1>>s2;
	int n=0;
	for (int i=0;s1[i];i++) s[n++]=s1[i]-' a ' +2;
	Len1=n;
	S[n++]=1;
	for (int i=0;s2[i];i++) s[n++]=s2[i]-' a ' +2;
	Construct array Build_sa (N,30);
	GetHeight (n);
	Second-division int l=0,r=n,mid=1,ans=0;
		while (l<=r) {mid= (l+r)/2;
			if (judge (N,mid)) {ans=mid;
		l=mid+1;
	else r=mid-1;
} cout<<ans<<endl;  }


Topic: E

Topic Description: The longest common substring that appears in at least half of the string of n strings and outputs, if more than one is sorted

Practice Analysis: concatenate n strings into a string, separating each string with a character that has never been seen before, and then the SA array, and then the height array.

1, the first two points to find at least half of the string in the longest occurrence of the common substring length Lmax

2, then according to the length of the case of Lmax to find the conditions of the string output in turn

Analysis of the difficulties: judge the height "I" sa[i] and SA "i-1" in the string if the same one, it means that this is a common substring of the string itself, which is not in the current string; only the sa "i-1" and the sa "I" are in two strings in order to make the number increase. So a POS array is needed to store the character Fu Yuan for each I representation, first in which string. Details of their own understanding, here only to do a brief analysis.

Code Show:

#include <iostream> #include <cstring> #include <algorithm> #include <cmath> using namespace std
;
const int maxn=200010; 
int S[MAXN];
int SA[MAXN],T[MAXN],T2[MAXN],C[MAXN],POS[MAXN];
	void Build_sa (int n,int m) {int i,*x=t,*y=t2;
	Initializes the base order for (i=0;i<m;i++) c[i]=0;
	for (I=0;i<n;++i) ++c[X[i]=s[i]];
	for (I=1;i<m;++i) c[i]+=c[i-1];
	for (i=n-1;i>=0;--i) sa[--c[x[i]]]=i;
		Multiply cardinal order for (int k=1;k<=n;k<<=1) {int = =;
		First, the second keyword for (i=n-k;i<n;++i) y[p++]=i is sorted according to the SA array directly;
		for (I=0;i<n;++i) if (sa[i]>=k) y[p++]=sa[i]-k;
		Reorder the first keyword for (i=0;i<m;i++) c[i]=0;
		for (I=0;i<n;++i) ++c[x[y[i]];
		for (I=1;i<m;++i) c[i]+=c[i-1];
		for (I=n-1;i>=0;--i) Sa[--c[x[y[i]]]]=y[i];
		reconstructs the x Array Swap (X,Y) based on the SA array;
		p=1;x[sa[0]]=0; for (I=1;i<n;++i) x[sa[i]]= Y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+k]==y[sa[i]+k]?
		p-1:p++;
		if (p>=n) break; 
	M=p;
} int HEIGHT[MAXN],RANK[MAXN]; void getheight (int n) {intk=0;
	for (int i=0;i<n;++i) rank[sa[i]]=i;
		for (int i=0;i<n;++i) {if (k) k--;
			if (Rank[i]) {int j=sa[rank[i]-1];
		while (S[i+k]==s[j+k]) k++;
	} height[rank[i]]=k;
	} bool Judge (int n,int l,int k) {int num=0;
	BOOL Vis[k];
	memset (Vis) (vis,false,sizeof);
			for (int i=1;i<n;++i) {if (height[i]<l) {memset (vis,false,sizeof (VIS));
		num=0;
			} else{if (Pos[sa[i]]==pos[sa[i-1]]) continue;
				if (!vis[pos[sa[i]]]) {vis[pos[sa[i]]]=true;
			num++;
				} if (!vis[pos[sa[i-1]]]) {vis[pos[sa[i-1]]]=true;
			num++;
		} if (num > (K/2)) return true;
return false;
	BOOL Print (int n,int l,int k) {int num=0;
	BOOL Vis[k];
	memset (Vis) (vis,false,sizeof); for (int i=0;i<n;++i) {if (height[i]<l) {if (num> (K/2)) {for (int j=0;j<l;j++) Cout<<char (s[j
				+sa[i-1]]+ ' a ');
			cout<<endl; 
			} memset (Vis) (vis,false,sizeof);
		num=0;
			} else{if (Pos[sa[i]]==pos[sa[i-1]]) continue; if (!vis[poS[sa[i]]) {vis[pos[sa[i]]]=true;
			num++;
				} if (!vis[pos[sa[i-1]]]) {vis[pos[sa[i-1]]]=true;
			num++;
}} return false;
	int main () {//Freopen ("Datain.txt", "R", stdin);
	Ios::sync_with_stdio (FALSE); 
	Cin.tie (0);
	int k;
		while (Cin>>k && k) {//Read preprocessing, the POS array is used to store the string number int n=0,tmp=0 where each letter begins;
			for (int i=0;i<k;++i) {string str;
			cin>>str;
				for (int j=0;str[j];++j) {pos[n]=tmp;
				s[n]=str[j]-' a ';
			n++;
			} pos[n]=tmp;
			s[n]=30+ (tmp++); 
		n++;
		}//construct suffix array build_sa (n,30+tmp+5);
		GetHeight (n);
		Binary finds the length of the longest common substring appearing in more than half of the strings ans int l=0,r=n,ans=6;
			while (l<=r) {int mid= (L+R)/2;
				if (judge (N,mid,k)) {ans=mid;
			l=mid+1;
		else r=mid-1;
		//Output if (ANS) print (n,ans,k); Else cout<< "?"
		<<endl; 
	cout<<endl;  }
}


Topic: D

Topic Description: Find the total number of common substrings with length greater than or equal to K in two strings

Practice Analysis: Concatenation of two strings into a string, separated by a character that has never been seen before, and then the SA array, and then the height array.

After the practice of using the concept of a monotonous stack, I do not specifically expand here, if you want to understand this problem first of their own Baidu under the monotonous stack concept, master its code implementation.

Sequentially iterate over the height array, dividing it so that each height value is greater than or equal to K, maintaining the current state with a single stack, storing the current number of the first string and the number of the second string.

This problem is very difficult to understand, I was rote, so put it in the end. , the following directly show the code, the self understand it, did me for several days.

Code Show:

#include <iostream> #include <cstring> #include <algorithm> #include <cmath> using namespace std
;
const int maxn=200010;
int S[MAXN],SA[MAXN],RANK[MAXN],T[MAXN],T2[MAXN],HEIGHT[MAXN],C[MAXN];
int sta[maxn][2];
	void Build_sa (int n,int m) {int i,*x=t,*y=t2;
	Initializes the base order for (i=0;i<m;i++) c[i]=0;
	for (I=0;i<n;++i) ++c[X[i]=s[i]];
	for (I=1;i<m;++i) c[i]+=c[i-1];
	for (i=n-1;i>=0;--i) sa[--c[x[i]]]=i;
		Multiply cardinal order for (int k=1;k<=n;k<<=1) {int = =;
		First, the second keyword for (i=n-k;i<n;++i) y[p++]=i is sorted according to the SA array directly;
		for (I=0;i<n;++i) if (sa[i]>=k) y[p++]=sa[i]-k;
		Reorder the first keyword for (i=0;i<m;i++) c[i]=0;
		for (I=0;i<n;++i) ++c[x[y[i]];
		for (I=1;i<m;++i) c[i]+=c[i-1];
		for (I=n-1;i>=0;--i) Sa[--c[x[y[i]]]]=y[i];
		reconstructs the x Array Swap (X,Y) based on the SA array;
		p=1;x[sa[0]]=0; for (I=1;i<n;++i) x[sa[i]]= Y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+k]==y[sa[i]+k]?
		p-1:p++;
		if (p>=n) break; 
	M=p; } void GetHeight (int n) {int k=0;
	for (int i=0;i<n;++i) rank[sa[i]]=i;
		for (int i=0;i<n;++i) {if (k) k--;
			if (Rank[i]) {int j=sa[rank[i]-1];
		while (S[i+k]==s[j+k]) k++;
	} height[rank[i]]=k;
	int main () {//freopen ("Datain.txt", "R", stdin);
	Ios::sync_with_stdio (FALSE); 
	Cin.tie (0);
	int k;
		while (Cin>>k && k) {//read into string s1,s2;
		cin>>s1>>s2;
		int Len1=s1.length (), n=0;
		for (int i=0;s1[i];i++) s[n++]=s1[i]-' A ' +2;
		S[n++]=1;
		for (int i=0;s2[i];i++) s[n++]=s2[i]-' A ' +2;
		s[n++]=0;
		Construct array Build_sa (N,70);
		GetHeight (n);	
		preprocessing for (int i=0;i<n;i++) Height[i]=max (0,height[i]-k+1);
		Sa[i-1] In the first string, Sa[i] is long ans=0,tot=0,top=0 in the second string;
			for (int i=1;i<n;i++) {if (height[i]<=0) {top=0;tot=0;
				}else{int cnt=0;
				if (SA[I-1]&LT;LEN1) {cnt++;tot+=height[i];
					while (top && height[i]<=sta[top-1][0]) {top--;
					tot+= (Height[i]-sta[top][0]) *sta[top][1];
				CNT+=STA[TOP][1]; } sta[top][0]=height[i];
				sta[top++][1]=cnt; 
			if (SA[I]&GT;LEN1) Ans+=tot;
		}//sa[i-1] In the second string, Sa[i] top=0;tot=0 in the first string;
			for (int i=1;i<n;i++) {if (height[i]<=0) {top=0;tot=0;
				}else{int cnt=0;
				if (SA[I-1]&GT;LEN1) {cnt++;tot+=height[i];
					while (top && height[i]<=sta[top-1][0]) {top--;
					tot+= (Height[i]-sta[top][0]) *sta[top][1];
				CNT+=STA[TOP][1];
				} Sta[top][0]=height[i];
				sta[top++][1]=cnt; 
			if (SA[I]&LT;LEN1) Ans+=tot;
	}}//Output cout<<ans<<endl;  }
}

Find a better suffix array template, as a generic template

#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace
Std
const int maxn=20000+100;
const int maxm=1000000+100;
    struct Suffixarray {int S[MAXN];
    int SA[MAXN],RNK[MAXN],HEIGHT[MAXN];
    int t1[maxn],t2[maxn],c[maxm],n;
        void Build_sa (int m) {int i,*x=t1,*y=t2;
        for (i=0; i<m; i++) c[i]=0;
        for (i=0; i<n; i++) c[x[i]=s[i]]++;
        for (I=1; i<m; i++) c[i]+=c[i-1];
        for (i=n-1; i>=0; i--) sa[--c[x[i]]]=i;
            for (int k=1; k<=n; k<<=1) {int = =;
            for (i=n-k; i<n; i++) y[p++]=i;
            For (i=0 i<n; i++) if (sa[i]>=k) y[p++]=sa[i]-k;
            for (i=0; i<m; i++) c[i]=0;
            for (i=0; i<n; i++) c[x[y[i]]]++;
            for (I=1; i<m; i++) c[i]+=c[i-1];
            for (i=n-1; i>=0; i--) sa[--c[x[y[i]]]]=y[i];
            Swap (x,y);
            P=1;
            x[sa[0]]=0;
      for (I=1; i<n; i++)          x[sa[i]]= Y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]?
            p-1:p++;
            if (p>=n) break;
        M=p;
        } void Build_height () {int i,j,k=0;
        for (i=0; i<n; i++) rnk[sa[i]]=i;
            For (i=0 i<n; i++) {if (k) k--;
            J=SA[RNK[I]-1];
            while (S[i+k]==s[j+k]) k++;
        Height[rnk[i]]=k;
        } bool Check (int l,int k) {//long l of the occurrence of K-times above the string int cnt=0;
            for (int i=1; i<n; i++) {if (height[i]<l)//New set of Start cnt=1;
                else {cnt++;
            if (cnt>=k) return true;
    return false;
        } void print (int l,int k) {int cnt=0;
            for (int i=1; i<n; i++) {if (height[i]<l)//New set of Start cnt=1;
                else {cnt++; if (cnt>=k) {for (int j=0;j<l;j++) printf ("%c", s[sa[i-1]+j]+ ' a '-1);
                    printf ("\ n");
                return;
 
}}}} sa;
    int main () {//freopen ("Datain.txt", "R", stdin);
    String str;
        while (CIN&GT;&GT;STR) {for (int i=0; str[i]; i++) sa.s[i]=str[i]-' a ' +1;
        Sa.n=str.length () +1;
        sa.s[sa.n-1]=0;
        Sa.build_sa (100+2);
        Sa.build_height ();
        int l=0,r=sa.n,maxlen,maxnum;
            while (l<=r) {int mid= (L+R)/2;
                if (Sa.check (2,mid)) {l=mid+1;
            Maxnum=mid;
        else r=mid-1;
        } l=0;
        R=SA.N;
            while (l<=r) {int mid= (L+R)/2;
                if (Sa.check (Mid,maxnum)) {l=mid+1;
            Maxlen=mid;
        else r=mid-1;
        } sa.print (Maxlen,maxnum);
    printf ("%d\n", maxnum);
return 0; }



Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.