Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 23 additions & 2 deletions StringAlgorithm/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public static int[] suffixArray(int[] s)
public static int[] suffixArray(int[] s, int upper)
```

長さ $n$ の文字列 `s` のSuffix Arrayとして、長さ $n$ のint配列を返す。 Suffix Array `sa`は $(0,1,\ldots ,n-1)$ の順列であって、各 $i=0,1,\cdots , n-2$ について `S[sa[i]..n) < s[sa[i+1]..n)` を満たすもの。
長さ $n$ の文字列 `s` のSuffix Arrayとして、長さ $n$ のint配列を返す。 Suffix Array `sa`は $(0,1,\ldots ,n-1)$ の順列であって、各 $i=0,1,\cdots , n-2$ について `s[sa[i]..n) < s[sa[i+1]..n)` を満たすもの。

### 制約

Expand Down Expand Up @@ -53,5 +53,26 @@ public static int[] lcpArray(int[] s, int[] sa)

- $O(n)$

## 使用例
### 使用例
[[https://atcoder.jp/contests/practice2/submissions/16585271]]

## zAlgorithm

```Java
// (1)
public static int[] zAlgorithm(java.lang.String s)
// (2)
public static int[] zAlgorithm(char[] s)
// (3)
public static int[] zAlgorithm(int[] s)
```

入力の長さを $n$ として、長さ $n$ の配列を返す。 $i$番目の要素は `s[0..n)` と `s[i..n)` のLCP(Longest Common Prefix)の長さ。

### 制約

- $0\le n\le 10^8$

### 計算量

- $O(n)$
50 changes: 39 additions & 11 deletions StringAlgorithm/StringAlgorithm.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
import java.util.Arrays;
import java.util.Comparator;
import java.util.function.Consumer;

class StringAlgorithm {
private static int[] saNaive(int[] s) {
int n = s.length;
Integer[] _sa = new Integer[n];
for (int i = 0; i < n; i++) {
_sa[i] = i;
}
Arrays.sort(_sa, (l, r) -> {
java.util.Arrays.sort(_sa, (l, r) -> {
while (l < n && r < n) {
if (s[l] != s[r]) return s[l] - s[r];
l++;
Expand All @@ -36,13 +32,13 @@ private static int[] saDoubling(int[] s) {
for (int k = 1; k < n; k *= 2) {
final int _k = k;
final int[] _rnk = rnk;
Comparator<Integer> cmp = (x, y) -> {
java.util.Comparator<Integer> cmp = (x, y) -> {
if (_rnk[x] != _rnk[y]) return _rnk[x] - _rnk[y];
int rx = x + _k < n ? _rnk[x + _k] : -1;
int ry = y + _k < n ? _rnk[y + _k] : -1;
return rx - ry;
};
Arrays.sort(_sa, cmp);
java.util.Arrays.sort(_sa, cmp);
tmp[_sa[0]] = 0;
for (int i = 1; i < n; i++) {
tmp[_sa[i]] = tmp[_sa[i - 1]] + (cmp.compare(_sa[i - 1], _sa[i]) < 0 ? 1 : 0);
Expand Down Expand Up @@ -102,8 +98,8 @@ private static int[] sais(int[] s, int upper) {
if (i < upper) sumL[i + 1] += sumS[i];
}

Consumer<int[]> induce = lms -> {
Arrays.fill(sa, -1);
java.util.function.Consumer<int[]> induce = lms -> {
java.util.Arrays.fill(sa, -1);
int[] buf = new int[upper + 1];
System.arraycopy(sumS, 0, buf, 0, upper + 1);
for (int d : lms) {
Expand All @@ -128,7 +124,7 @@ private static int[] sais(int[] s, int upper) {
};

int[] lmsMap = new int[n + 1];
Arrays.fill(lmsMap, -1);
java.util.Arrays.fill(lmsMap, -1);
int m = 0;
for (int i = 1; i < n; i++) {
if (!ls[i - 1] && ls[i]) {
Expand Down Expand Up @@ -205,7 +201,7 @@ public static int[] suffixArray(int[] s) {
for (int i = 0; i < n; i++) {
idx[i] = i;
}
Arrays.sort(idx, (l, r) -> s[l] - s[r]);
java.util.Arrays.sort(idx, (l, r) -> s[l] - s[r]);
int[] s2 = new int[n];
int now = 0;
for (int i = 0; i < n; i++) {
Expand Down Expand Up @@ -265,4 +261,36 @@ public static int[] lcpArray(char[] s, int[] sa) {
public static int[] lcpArray(java.lang.String s, int[] sa) {
return lcpArray(s.toCharArray(), sa);
}

public static int[] zAlgorithm(int[] s) {
int n = s.length;
if (n == 0) return new int[0];
int[] z = new int[n];
for (int i = 1, j = 0; i < n; i++) {
int k = j + z[j] <= i ? 0 : Math.min(j + z[j] - i, z[i - j]);
while (i + k < n && s[k] == s[i + k]) k++;
z[i] = k;
if (j + z[j] < i + z[i]) j = i;
}
z[0] = n;
return z;
}

public static int[] zAlgorithm(char[] s) {
int n = s.length;
if (n == 0) return new int[0];
int[] z = new int[n];
for (int i = 1, j = 0; i < n; i++) {
int k = j + z[j] <= i ? 0 : Math.min(j + z[j] - i, z[i - j]);
while (i + k < n && s[k] == s[i + k]) k++;
z[i] = k;
if (j + z[j] < i + z[i]) j = i;
}
z[0] = n;
return z;
}

public static int[] zAlgorithm(String s) {
return zAlgorithm(s.toCharArray());
}
}