|
@@ -4,46 +4,6 @@ import (
|
|
|
"fmt"
|
|
|
)
|
|
|
|
|
|
-func nextPerm(nums []int) bool {
|
|
|
- n := len(nums)
|
|
|
- if n < 2 {
|
|
|
- return false
|
|
|
- }
|
|
|
- i := n - 2
|
|
|
- for ; 0 <= i && nums[i+1] <= nums[i]; i-- {
|
|
|
- }
|
|
|
- if i == -1 {
|
|
|
- return false
|
|
|
- }
|
|
|
- j := i + 1
|
|
|
- for ; j+1 < n && nums[i] < nums[j+1]; j++ {
|
|
|
- }
|
|
|
- nums[i], nums[j] = nums[j], nums[i]
|
|
|
- for l, r := i+1, n-1; l < r; l, r = l+1, r-1 {
|
|
|
- nums[l], nums[r] = nums[r], nums[l]
|
|
|
- }
|
|
|
- return true
|
|
|
-}
|
|
|
-
|
|
|
-func countGroup(s string, perm []int) int {
|
|
|
- n, k := len(s), len(perm)
|
|
|
- prevByte := s[perm[0]]
|
|
|
- cnt := 1
|
|
|
- for offset := 0; offset < n; offset += k {
|
|
|
- i := 0
|
|
|
- if offset == 0 {
|
|
|
- i = 1
|
|
|
- }
|
|
|
- for ; i < k; i++ {
|
|
|
- if s[offset+perm[i]] != prevByte {
|
|
|
- cnt++
|
|
|
- }
|
|
|
- prevByte = s[offset+perm[i]]
|
|
|
- }
|
|
|
- }
|
|
|
- return cnt
|
|
|
-}
|
|
|
-
|
|
|
func main() {
|
|
|
var N, k int
|
|
|
fmt.Scan(&N)
|
|
@@ -51,17 +11,58 @@ func main() {
|
|
|
fmt.Scan(&k)
|
|
|
var S string
|
|
|
fmt.Scan(&S)
|
|
|
- perm := make([]int, k)
|
|
|
- for i := range perm {
|
|
|
- perm[i] = i
|
|
|
+ n := len(S)
|
|
|
+ // edge[x][y] means the weight of edge: x -> y
|
|
|
+ // init[x][y] means the weight of edge: init point x -> y
|
|
|
+ edge, init := make([][]int, k), make([][]int, k)
|
|
|
+ for i := 0; i < k; i++ {
|
|
|
+ edge[i], init[i] = make([]int, k), make([]int, k)
|
|
|
}
|
|
|
- minGroup := countGroup(S, perm)
|
|
|
- for nextPerm(perm) {
|
|
|
- groupCnt := countGroup(S, perm)
|
|
|
- if groupCnt < minGroup {
|
|
|
- minGroup = groupCnt
|
|
|
+ for x := 0; x < k; x++ {
|
|
|
+ for y := 0; y < k; y++ {
|
|
|
+ if x != y {
|
|
|
+ for o := 0; o < n; o += k {
|
|
|
+ if S[o+x] != S[o+y] {
|
|
|
+ edge[x][y]++
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for o := 0; o < n-k; o += k {
|
|
|
+ if S[o+x] != S[o+k+y] {
|
|
|
+ init[x][y]++
|
|
|
+ }
|
|
|
+ } // Note: y -> x and x -> y is NOT THE SAME INIT edge!!!
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ dp := make([][]int, 1<<uint(k))
|
|
|
+ for i := range dp {
|
|
|
+ dp[i] = make([]int, k)
|
|
|
+ }
|
|
|
+ const inf = 1000000
|
|
|
+ ans := inf
|
|
|
+ for beg := 0; beg < k; beg++ {
|
|
|
+ for i := range dp {
|
|
|
+ for j := range dp[i] {
|
|
|
+ dp[i][j] = inf
|
|
|
+ }
|
|
|
+ }
|
|
|
+ dp[1<<uint(beg)][beg] = 1
|
|
|
+ for mask := 0; mask < (1 << uint(k)); mask++ {
|
|
|
+ for i := 0; i < k; i++ {
|
|
|
+ if dp[mask][i] < inf {
|
|
|
+ for j := 0; j < k; j++ {
|
|
|
+ newset := mask | (1 << uint(j))
|
|
|
+ if newset != mask {
|
|
|
+ dp[newset][j] = minInt(dp[newset][j], dp[mask][i]+edge[i][j])
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for i := 0; i < k; i++ {
|
|
|
+ ans = minInt(ans, dp[(1<<uint(k))-1][i]+init[i][beg])
|
|
|
}
|
|
|
}
|
|
|
- fmt.Printf("Case #%d: %d\n", cid+1, minGroup)
|
|
|
+ fmt.Printf("Case #%d: %d\n", cid+1, ans)
|
|
|
}
|
|
|
}
|