go语言几种算法(三)
13、Rabin-Karp(Rabin-Karp字符串匹配算法)
package main
import (
"fmt"
)
const base = 16777619
func Search(txt string, patterns []string) []string {
in := indices(txt, patterns)
matches := make([]string, len(in))
i := 0
for j, p := range patterns {
if _, ok := in[j]; ok {
matches[i] = p
i++
}
}
return matches
}
func indices(txt string, patterns []string) map[int]int {
n, m := len(txt), minLen(patterns)
matches := make(map[int]int)
if n < m || len(patterns) == 0 {
return matches
}
var mult uint32 = 1 // mult = base^(m-1)
for i := 0; i < m-1; i++ {
mult = (mult * base)
}
hp := hashPatterns(patterns, m)
h := hash(txt[:m])
for i := 0; i < n-m+1 && len(hp) > 0; i++ {
if i > 0 {
h = h - mult*uint32(txt[i-1])
h = h*base + uint32(txt[i+m-1])
}
if mps, ok := hp[h]; ok {
for _, pi := range mps {
pat := patterns[pi]
e := i + len(pat)
if _, ok := matches[pi]; !ok && e <= n && pat == txt[i:e] {
matches[pi] = i
}
}
}
}
return matches
}
func hash(s string) uint32 {
var h uint32
for i := 0; i < len(s); i++ {
h = (h*base + uint32(s[i]))
}
return h
}
func hashPatterns(patterns []string, l int) map[uint32][]int {
m := make(map[uint32][]int)
for i, t := range patterns {
h := hash(t[:l])
if _, ok := m[h]; ok {
m[h] = append(m[h], i)
} else {
m[h] = []int{i}
}
}
return m
}
func minLen(patterns []string) int {
if len(patterns) == 0 {
return 0
}
m := len(patterns[0])
for i := range patterns {
if m > len(patterns[i]) {
m = len(patterns[i])
}
}
return m
}
func main() {
txt := "Australia is a country and continent surrounded by the Indian and Pacific oceans."
patterns := []string{"and", "the", "surround", "Pacific", "Germany"}
matches := Search(txt, patterns)
fmt.Println(matches)
}
14、LIFO Stack and FIFO Queue(栈,队列)
package main
import (
"fmt"
)
type Node struct {
Value int
}
func (n *Node) String() string {
return fmt.Sprint(n.Value)
}
// NewStack returns a new stack.
func NewStack() *Stack {
return &Stack{}
}
// Stack is a basic LIFO stack that resizes as needed.
type Stack struct {
nodes []*Node
count int
}
// Push adds a node to the stack.
func (s *Stack) Push(n *Node) {
s.nodes = append(s.nodes[:s.count], n)
s.count++
}
// Pop removes and returns a node from the stack in last to first order.
func (s *Stack) Pop() *Node {
if s.count == 0 {
return nil
}
s.count--
return s.nodes[s.count]
}
// NewQueue returns a new queue with the given initial size.
func NewQueue(size int) *Queue {
return &Queue{
nodes: make([]*Node, size),
size: size,
}
}
// Queue is a basic FIFO queue based on a circular list that resizes as needed.
type Queue struct {
nodes []*Node
size int
head int
tail int
count int
}
// Push adds a node to the queue.
func (q *Queue) Push(n *Node) {
if q.head == q.tail && q.count > 0 {
nodes := make([]*Node, len(q.nodes)+q.size)
copy(nodes, q.nodes[q.head:])
copy(nodes[len(q.nodes)-q.head:], q.nodes[:q.head])
q.head = 0
q.tail = len(q.nodes)
q.nodes = nodes
}
q.nodes[q.tail] = n
q.tail = (q.tail + 1) % len(q.nodes)
q.count++
}
// Pop removes and returns a node from the queue in first to last order.
func (q *Queue) Pop() *Node {
if q.count == 0 {
return nil
}
node := q.nodes[q.head]
q.head = (q.head + 1) % len(q.nodes)
q.count--
return node
}
func main() {
s := NewStack()
s.Push(&Node{3})
s.Push(&Node{5})
s.Push(&Node{7})
s.Push(&Node{9})
fmt.Println(s.Pop(), s.Pop(), s.Pop(), s.Pop())
q := NewQueue(1)
q.Push(&Node{2})
q.Push(&Node{4})
q.Push(&Node{6})
q.Push(&Node{8})
fmt.Println(q.Pop(), q.Pop(), q.Pop(), q.Pop())
}
15、Median of Medians(中位数的中位数)
package main
import "fmt"
type Node struct {
prev *Node
next *Node
key interface{}
}
type List struct {
head *Node
tail *Node
}
func (L *List) Insert(key interface{}) {
list := &Node{
next: L.head,
key: key,
}
if L.head != nil {
L.head.prev = list
}
L.head = list
l := L.head
for l.next != nil {
l = l.next
}
L.tail = l
}
func (l *List) Display() {
list := l.head
for list != nil {
fmt.Printf("%+v ->", list.key)
list = list.next
}
fmt.Println()
}
func Display(list *Node) {
for list != nil {
fmt.Printf("%v ->", list.key)
list = list.next
}
fmt.Println()
}
func ShowBackwards(list *Node) {
for list != nil {
fmt.Printf("%v <-", list.key)
list = list.prev
}
fmt.Println()
}
func (l *List) Reverse() {
curr := l.head
var prev *Node
l.tail = l.head
for curr != nil {
next := curr.next
curr.next = prev
prev = curr
curr = next
}
l.head = prev
Display(l.head)
}
func main() {
link := List{}
link.Insert(5)
link.Insert(9)
link.Insert(13)
link.Insert(22)
link.Insert(28)
link.Insert(36)
fmt.Println("\n==============================\n")
fmt.Printf("Head: %v\n", link.head.key)
fmt.Printf("Tail: %v\n", link.tail.key)
link.Display()
fmt.Println("\n==============================\n")
fmt.Printf("head: %v\n", link.head.key)
fmt.Printf("tail: %v\n", link.tail.key)
link.Reverse()
fmt.Println("\n==============================\n")
}
16、Longest Common Sub-sequence(最长公共子序列)
package main
import "fmt"
type Node struct {
prev *Node
next *Node
key interface{}
}
type List struct {
head *Node
tail *Node
}
func (L *List) Insert(key interface{}) {
list := &Node{
next: L.head,
key: key,
}
if L.head != nil {
L.head.prev = list
}
L.head = list
l := L.head
for l.next != nil {
l = l.next
}
L.tail = l
}
func (l *List) Display() {
list := l.head
for list != nil {
fmt.Printf("%+v ->", list.key)
list = list.next
}
fmt.Println()
}
func Display(list *Node) {
for list != nil {
fmt.Printf("%v ->", list.key)
list = list.next
}
fmt.Println()
}
func ShowBackwards(list *Node) {
for list != nil {
fmt.Printf("%v <-", list.key)
list = list.prev
}
fmt.Println()
}
func (l *List) Reverse() {
curr := l.head
var prev *Node
l.tail = l.head
for curr != nil {
next := curr.next
curr.next = prev
prev = curr
curr = next
}
l.head = prev
Display(l.head)
}
func main() {
link := List{}
link.Insert(5)
link.Insert(9)
link.Insert(13)
link.Insert(22)
link.Insert(28)
link.Insert(36)
fmt.Println("\n==============================\n")
fmt.Printf("Head: %v\n", link.head.key)
fmt.Printf("Tail: %v\n", link.tail.key)
link.Display()
fmt.Println("\n==============================\n")
fmt.Printf("head: %v\n", link.head.key)
fmt.Printf("tail: %v\n", link.tail.key)
link.Reverse()
fmt.Println("\n==============================\n")
}
17、Levenshtein distance(编辑距离-字符串相似度算法)
package main
import "fmt"
func levenshtein(str1, str2 []rune) int {
s1len := len(str1)
s2len := len(str2)
column := make([]int, len(str1)+1)
for y := 1; y <= s1len; y++ {
column[y] = y
}
for x := 1; x <= s2len; x++ {
column[0] = x
lastkey := x - 1
for y := 1; y <= s1len; y++ {
oldkey := column[y]
var incr int
if str1[y-1] != str2[x-1] {
incr = 1
}
column[y] = minimum(column[y]+1, column[y-1]+1, lastkey+incr)
lastkey = oldkey
}
}
return column[s1len]
}
func minimum(a, b, c int) int {
if a < b {
if a < c {
return a
}
} else {
if b < c {
return b
}
}
return c
}
func main(){
var str1 = []rune("Asheville")
var str2 = []rune("Arizona")
fmt.Println("Distance between Asheville and Arizona:",levenshtein(str1,str2))
str1 = []rune("Python")
str2 = []rune("Peithen")
fmt.Println("Distance between Python and Peithen:",levenshtein(str1,str2))
str1 = []rune("Orange")
str2 = []rune("Apple")
fmt.Println("Distance between Orange and Apple:",levenshtein(str1,str2))
}
18、Knuth–Morris–Pratt(KMP-克努斯-莫里斯-普拉特算法-子串匹配算法)
package main
import (
"fmt"
)
const (
PatternSize int = 100
)
func SearchNext(haystack string, needle string) int {
retSlice := KMP(haystack, needle)
if len(retSlice) > 0 {
return retSlice[len(retSlice)-1]
}
return -1
}
func SearchString(haystack string, needle string) int {
retSlice := KMP(haystack, needle)
if len(retSlice) > 0 {
return retSlice[0]
}
return -1
}
func KMP(haystack string, needle string) []int {
next := preKMP(needle)
i := 0
j := 0
m := len(needle)
n := len(haystack)
x := []byte(needle)
y := []byte(haystack)
var ret []int
//got zero target or want, just return empty result
if m == 0 || n == 0 {
return ret
}
//want string bigger than target string
if n < m {
return ret
}
for j < n {
for i > -1 && x[i] != y[j] {
i = next[i]
}
i++
j++
//fmt.Println(i, j)
if i >= m {
ret = append(ret, j-i)
//fmt.Println("find:", j, i)
i = next[i]
}
}
return ret
}
func preMP(x string) [PatternSize]int {
var i, j int
length := len(x) - 1
var mpNext [PatternSize]int
i = 0
j = -1
mpNext[0] = -1
for i < length {
for j > -1 && x[i] != x[j] {
j = mpNext[j]
}
i++
j++
mpNext[i] = j
}
return mpNext
}
func preKMP(x string) [PatternSize]int {
var i, j int
length := len(x) - 1
var kmpNext [PatternSize]int
i = 0
j = -1
kmpNext[0] = -1
for i < length {
for j > -1 && x[i] != x[j] {
j = kmpNext[j]
}
i++
j++
if x[i] == x[j] {
kmpNext[i] = kmpNext[j]
} else {
kmpNext[i] = j
}
}
return kmpNext
}
func main() {
fmt.Println("Search First Position String:\n")
fmt.Println(SearchString("cocacola", "co"))
fmt.Println(SearchString("Australia", "lia"))
fmt.Println(SearchString("cocacola", "cx"))
fmt.Println(SearchString("AABAACAADAABAABA", "AABA"))
fmt.Println("\nSearch Last Position String:\n")
fmt.Println(SearchNext("cocacola", "co"))
fmt.Println(SearchNext("Australia", "lia"))
fmt.Println(SearchNext("cocacola", "cx"))
fmt.Println(SearchNext("AABAACAADAABAABAAABAACAADAABAABA", "AABA"))
}
发表评论: