Given a string str of size N, the task is to find the suffix array of the given string.
Note: A suffix array is a sorted array of all suffixes of a given string.
Examples:
Input: str = “prince”
Output: 4 5 2 3 0 1
Explanation: The suffixes are
0 prince 4 ce
1 rince Sort the suffixes 5 e
2 ince —————-> 2 ince
3 nce alphabetically 3 nce
4 ce 0 prince
5 e 1 rinceInput: str = “abcd”
Output: 0 1 2 3
Approach: The methods of suffix array finding for any string are discussed here. In this article, the focus is on finding suffix array for strings with no repeating character. It is a simple implementation based problem. Follow the steps mentioned below to solve the problem:
- Count occurrence of each character.
- Find prefix sum of it.
- Find start array by start[0] = 0, start[i+1] = prefix[i] for all i > 0 .
- Find start array containing the index of the substring (suffix) with starting character of the respective column.
Follow the illustration below for better understanding.
Illustration:
Consider string “prince”:
Given below is the suffix table
char a b c d e f g h i j k l m n o p q r s t u v w x y z count 0 0 1 0 1 0 0 0 1 0 0 0 0 1 0 1 0 1 0 0 0 0 0 0 0 0 prefix 0 0 1 1 2 2 2 2 3 3 3 3 3 4 4 5 5 6 6 6 6 6 6 6 6 6 start 0 0 0 1 1 2 2 2 2 3 3 3 3 3 4 4 5 5 6 6 6 6 6 6 6 6 For char ‘r’ start value is 5 .
Implies substring (suffix) starting with char ‘r’ i.e. “rince” has rank 5 .
Rank is position in suffix array. ( 1 “rince” ) implies 5th position in suffix array ), refer first table.
Similarly, start value of char ‘n’ is 3 . Implies ( 3 “nce” ) 3rd position in suffix array .
Below is the implementation of the above approach
// C++ code to implement above approach #include <bits/stdc++.h> using namespace std;
// Function to calculate the suffix array void suffixArray(string str, int N)
{ // arr[] is array to count
// occurrence of each character
int arr[30] = { 0 };
for ( int i = 0; i < N; i++) {
arr[str[i] - 'a' ]++;
}
// Finding prefix count of character
for ( int i = 1; i < 30; i++) {
arr[i] = arr[i] + arr[i - 1];
}
int start[30];
start[0] = 0;
for ( int i = 0; i < 29; i++) {
start[i + 1] = arr[i];
}
int ans[N] = { 0 };
// Iterating string in reverse order
for ( int i = N - 1; i >= 0; i--) {
// Storing suffix array in ans[]
ans[start[str[i] - 'a' ]] = i;
}
for ( int i = 0; i < N; i++)
cout << ans[i] << " " ;
} // Driver code int main()
{ string str = "prince" ;
int N = str.length();
suffixArray(str, N);
return 0;
} |
// Java program for the above approach import java.io.*;
import java.lang.*;
import java.util.*;
class GFG {
// Function to calculate the suffix array
static void suffixArray(String str, int N)
{
// arr[] is array to count
// occurrence of each character
int arr[] = new int [ 30 ];
for ( int i = 0 ; i < N; i++) {
arr[str.charAt(i) - 'a' ]++;
}
// Finding prefix count of character
for ( int i = 1 ; i < 30 ; i++) {
arr[i] = arr[i] + arr[i - 1 ];
}
int start[] = new int [ 30 ];
start[ 0 ] = 0 ;
for ( int i = 0 ; i < 29 ; i++) {
start[i + 1 ] = arr[i];
}
int ans[] = new int [N];
// Iterating string in reverse order
for ( int i = N - 1 ; i >= 0 ; i--) {
// Storing suffix array in ans[]
ans[start[str.charAt(i) - 'a' ]] = i;
}
for ( int i = 0 ; i < N; i++)
System.out.print(ans[i] + " " );
}
// Driver code
public static void main (String[] args)
{
String str = "prince" ;
int N = str.length();
suffixArray(str, N);
}
} // This code is contributed by hrithikgarg03188 |
# Python code for the above approach # Function to calculate the suffix array def suffixArray( str , N):
# arr[] is array to count
# occurrence of each character
arr = [ 0 ] * 30
for i in range (N):
arr[ ord ( str [i]) - ord ( 'a' )] + = 1
# Finding prefix count of character
for i in range ( 1 , 30 ):
arr[i] = arr[i] + arr[i - 1 ]
start = [ 0 ] * 30
start[ 0 ] = 0
for i in range ( 29 ):
start[i + 1 ] = arr[i]
ans = [ 0 ] * N
# Iterating string in reverse order
for i in range (N - 1 , 0 , - 1 ):
# Storing suffix array in ans[]
ans[start[ ord ( str [i]) - ord ( 'a' )]] = i
for i in range (N):
print (ans[i], end = " " )
# Driver code str = "prince"
N = len ( str )
suffixArray( str , N)
# This code is contributed by gfgking |
// C# code to implement above approach using System;
class GFG
{ // Function to calculate the suffix array
static void suffixArray( string str, int N)
{
// arr[] is array to count
// occurrence of each character
int [] arr = new int [30];
for ( int i = 0; i < N; i++) {
arr[str[i] - 'a' ]++;
}
// Finding prefix count of character
for ( int i = 1; i < 30; i++) {
arr[i] = arr[i] + arr[i - 1];
}
int [] start = new int [30];
start[0] = 0;
for ( int i = 0; i < 29; i++) {
start[i + 1] = arr[i];
}
int [] ans = new int [N];
// Iterating string in reverse order
for ( int i = N - 1; i >= 0; i--) {
// Storing suffix array in ans[]
ans[start[str[i] - 'a' ]] = i;
}
for ( int i = 0; i < N; i++) {
Console.Write(ans[i]);
Console.Write( " " );
}
}
// Driver code
public static int Main()
{
string str = "prince" ;
int N = str.Length;
suffixArray(str, N);
return 0;
}
} // This code is contributed by Taranpreet |
<script> // JavaScript code for the above approach
// Function to calculate the suffix array
function suffixArray(str, N) {
// arr[] is array to count
// occurrence of each character
let arr = new Array(30).fill(0);
for (let i = 0; i < N; i++) {
arr[str[i].charCodeAt(0) - 'a' .charCodeAt(0)]++;
}
// Finding prefix count of character
for (let i = 1; i < 30; i++) {
arr[i] = arr[i] + arr[i - 1];
}
let start = new Array(30)
start[0] = 0;
for (let i = 0; i < 29; i++) {
start[i + 1] = arr[i];
}
let ans = new Array(N).fill(0)
// Iterating string in reverse order
for (let i = N - 1; i >= 0; i--) {
// Storing suffix array in ans[]
ans[start[str[i].charCodeAt(0) - 'a' .charCodeAt(0)]] = i;
}
for (let i = 0; i < N; i++)
document.write(ans[i] + " " )
}
// Driver code
let str = "prince" ;
let N = str.length;
suffixArray(str, N);
// This code is contributed by Potta Lokesh
</script>
|
4 5 2 3 0 1
Time Complexity: O(N)
Auxiliary Space: O(N)