Skip to content

Commit 10d04c6

Browse files
authored
Merge pull request #11 from harry0000/z-algorithm
Add Z algorithm
2 parents aca6c19 + ad634f3 commit 10d04c6

File tree

6 files changed

+68
-13
lines changed

6 files changed

+68
-13
lines changed

.github/workflows/ci.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ jobs:
88
fail-fast: false
99
matrix:
1010
name: [ "test" ]
11-
scala: [ 3.3.0, 3.3.1 ]
11+
scala: [ 3.3.0, 3.4.1 ]
1212
java: [ 20, 21 ]
1313
include:
1414
- name: "format"
15-
scala: 3.3.1
15+
scala: 3.4.1
1616
java: 21
1717
exclude:
1818
- name: "test"

build.sbt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
lazy val supportedScalaVersions = List("3.3.1", "3.3.0")
1+
lazy val supportedScalaVersions = List("3.4.1", "3.3.0")
22

33
lazy val root = project
44
.in(file("."))
@@ -16,6 +16,6 @@ lazy val root = project
1616
"-unchecked",
1717
"-Wunused:all"
1818
),
19-
libraryDependencies += "org.scalameta" %% "munit" % "0.7.29" % Test,
19+
libraryDependencies += "org.scalameta" %% "munit" % "1.0.0-M11" % Test,
2020
Test / parallelExecution := false
2121
)

src/main/scala/io/github/acl4s/ModInt.scala

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,7 @@ object Modulus {
9090
inline def apply[T <: Int](): Modulus[T] = Mod(compiletime.constValue[T])
9191
}
9292

93-
final case class StaticModInt[T <: Int] private (private[this] var _value: Int)(using m: Modulus[T])
94-
extends ModIntBase[T] {
93+
final case class StaticModInt[T <: Int] private (private var _value: Int)(using m: Modulus[T]) extends ModIntBase[T] {
9594
override type Self = StaticModInt[T]
9695
override val mod: T = m.value
9796

@@ -204,7 +203,7 @@ object ModInt998244353 {
204203
def apply(value: Long): ModInt998244353 = StaticModInt(value)
205204
}
206205

207-
final case class DynamicModInt private (private[this] var _value: Int) extends ModIntBase[Int] {
206+
final case class DynamicModInt private (private var _value: Int) extends ModIntBase[Int] {
208207
override type Self = DynamicModInt
209208
override val mod: Int = DynamicModInt.bt.m
210209

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package io.github.acl4s
2+
3+
import scala.reflect.ClassTag
4+
5+
/**
6+
* Reference:
7+
* D. Gusfield,
8+
* Algorithms on Strings, Trees, and Sequences: Computer Science and
9+
* Computational Biology
10+
*/
11+
private[acl4s] def zAlgorithmImpl[T: ClassTag](s: Array[T]): Array[Int] = {
12+
val n = s.length
13+
if (n == 0) {
14+
return Array.empty
15+
}
16+
val z = new Array[Int](n)
17+
z(0) = 0
18+
var j = 0
19+
for (i <- 1 until n) {
20+
var k = if (j + z(j) <= i) { 0 }
21+
else { Math.min(j + z(j) - i, z(i - j)) }
22+
while (i + k < n && s(k) == s(i + k)) {
23+
k += 1
24+
}
25+
z(i) = k
26+
if (j + z(j) < i + z(i)) {
27+
j = i
28+
}
29+
}
30+
z(0) = n
31+
z
32+
}
33+
34+
def zAlgorithm(s: String): Array[Int] = zAlgorithmImpl(s.toCharArray)

src/main/scala/io/github/acl4s/TwoSAT.scala

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package io.github.acl4s
22

3+
import scala.util.boundary, boundary.break
4+
35
/**
46
* Reference:
57
* B. Aspvall, M. Plass, and R. Tarjan,
@@ -28,12 +30,12 @@ class TwoSAT(private val n: Int) {
2830

2931
def satisfiable(): Boolean = {
3032
val (_, id) = scc.sccIds()
31-
(0 until n).foreach(i => {
32-
if (id(2 * i) == id(2 * i + 1)) {
33-
return false
33+
boundary {
34+
for (i <- 0 until n) {
35+
if (id(2 * i) == id(2 * i + 1)) { break(false) }
36+
answer(i) = id(2 * i) < id(2 * i + 1)
3437
}
35-
answer(i) = id(2 * i) < id(2 * i + 1)
36-
})
37-
true
38+
true
39+
}
3840
}
3941
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package io.github.acl4s
2+
3+
class StringSuite extends munit.FunSuite {
4+
5+
test("zAlgorithm") {
6+
{
7+
val str = "abracadabra";
8+
val lcp = zAlgorithm(str)
9+
10+
assertEquals(lcp.toSeq, Seq(11, 0, 0, 1, 0, 1, 0, 4, 0, 0, 1))
11+
}
12+
{
13+
val str = "ababababa"
14+
val lcp = zAlgorithm(str)
15+
16+
assertEquals(lcp.toSeq, Seq(9, 0, 7, 0, 5, 0, 3, 0, 1))
17+
}
18+
}
19+
20+
}

0 commit comments

Comments
 (0)