The sense suffix array is hard to learn to say = = but it's finally gnawing down.
First, we need to understand the principle of the multiplication method construction.
Set the length of the original string to n for each substring we add it to the string of length 2^k (2^k-1<n<=2^k)
For example, the strings of ABA are ABA '/' BA '/' a ', '
Each operation we can drain the size of all substrings of length 2^x
such as the sequencing process of the ABA sequence.
First pass a A B
Second pass a ' + ' AB BA
The third time a '/' \ ' "* * * ' ABA '"
After we understand this, we can write a nlog^2n fast-line implementation method.
This is a good way to write if n<=10^5 to use it safely.
//SA nlog^2n#include <cstdio>#include<cstring>#include<cmath>#include<algorithm>#defineRep (i,n) for (int i=1;i<=n;++i)#defineIMAX (X>Y?X:Y)#defineIMAX (X<Y?X:Y)using namespacestd;Const intn=100010;structnode{intX,y,ma;} Tr[n];CharCh[n];intr[n<<1],sa[n];intN;BOOLCMP (node Aa,node bb) {returnaa.x<bb.x| | (aa.x==bb.x&&aa.y<bb.y);}voidGetsa () { for(intI=1;1<< (I-1) <n;++i) {rep (j,n) {tr[j].x=R[j]; Tr[j].y=r[j+ (1<<i-1)]; Tr[j].ma=J; } sort (Tr+1, tr+1+n,cmp); intCnt=0; Rep (j,n) r[tr[j].ma]=tr[j].x==tr[j-1].x&&tr[j].y==tr[j-1].y?cnt:++CNT; } Rep (J,n) Sa[r[j]]=J;}intMain () {scanf ("%s", ch+1); N=strlen (ch+1); Rep (i,n) r[i]=Ch[i]; Getsa (); printf ("RANK:"); Rep (i,n) printf ("%d", R[i]); printf ("\nsa:"); Rep (i,n) printf ("%d", Sa[i]); return 0;}
However, given the specificity of the rank array (a certain <=n), we can also use cardinality sorting to reduce the complexity to NLOGN
So we can solve the n<=10^6 problem.
But this is quite easy to write wrong and need to master the principle of cardinal sort first
The cardinality sort is intuitive and requires a list to be done, but it's also easy to do it with just one array.
Specifically, you can refer to the code
//SA Nlogn (N=1 need a special sentence here too lazy to write)#include <cstdio>#include<cstring>#include<cmath>#include<algorithm>#defineRep (i,n) for (int i=1;i<=n;++i)#defineIMAX (X>Y?X:Y)#defineIMAX (X<Y?X:Y)using namespacestd;Const intn=1000010, s= -;//usually the characters are between 0-127.CharCh[n];intsum[s],r[2][n<<1],sa[2][n];intn,t;voidGetsa (inti)//The SA value in this is not the last SA value but ensures that the corresponding rank value is equal to a certain neighbor so as to facilitate comparison of the size{memset (sum,0,sizeof(sum)); Rep (J,n)++sum[r[t][j+I]]; for(intj=1; j<s;++j) Sum[j]+=sum[j-1]; Rep (j,n) sa[0][sum[r[t][j+i]]--]=J; memset (SUM,0,sizeof(sum)); Rep (J,n)++Sum[r[t][j]]; for(intj=1; j<s;++j) Sum[j]+=sum[j-1]; for(intj=n;j;--j)//The base sort starts from the second order and must be searched in reverse order (if you don't understand it, search for the base sort)sa[1][sum[r[t][sa[0][j]]]--]=sa[0][j];}intMain () {scanf ("%s", ch+1); N=strlen (ch+1); Rep (I,n) Sum[ch[i]]=1; for(intI=1; i<s;++i) sum[i]+=sum[i-1]; Rep (i,n) r[0][i]=sum[ch[i]];//sum outside the function is used to find the initial rank for(intI=1; i<n;i<<=1) {Getsa (i); T^=1; Rep (j,n) r[t][sa[1][j]]=r[t^1][sa[1][j]]==r[t^1][sa[1][j-1]]&&r[t^1][sa[1][j]+i]==r[t^1][sa[1][j-1]+i]?r[t][sa[1][j-1]]:r[t][sa[1][j-1]]+1; if(r[t][sa[1][n]]==n) Break;//It's already lined up so you can quit early.} printf ("RANK:"); Rep (i,n) printf ("%d", R[t][i]); printf ("\nsa:"); Rep (i,n) printf ("%d", sa[1][i]); return 0;}
To construct the SA and rank arrays in the suffix array using multiplication method