package main import "sync" func LongestDupSubstringBruteforce(s string) string { strLen := len(s) if strLen < 2 { return "" } res := "" for ln := 1; ln < strLen; ln++ { for i := 0; i <= strLen-ln; i++ { word1 := s[i : i+ln] count := 0 for j := 0; j <= strLen-ln; j++ { word2 := s[j : j+ln] if word1 == word2 { count++ if count > 1 { res = word1 break } } } } } return res } func LongestDupSubstringReversedBruteforce(s string) string { strLen := len(s) if strLen < 2 { return "" } for ln := strLen - 1; ln >= 1; ln-- { for i := strLen - ln; i >= 0; i-- { word1 := s[i : i+ln] count := 0 for j := strLen - ln; j >= 0; j-- { word2 := s[j : j+ln] if word1 == word2 { count++ if count > 1 { return word1 } } } } } return "" } func LongestDupSubstringSmartforce(s string) string { strLen := len(s) if strLen < 2 { return "" } indicesCurrent := []int{} indicesNext := []int{} res := "" for i := 0; i < strLen-len(res); i++ { for j := 0; j < strLen; j++ { indicesCurrent = append(indicesCurrent, j) } for ln := 1; ln <= strLen-i; ln++ { word1 := s[i : i+ln] for _, index := range indicesCurrent { if index+ln > strLen { continue } word2 := s[index : index+ln] if (word1 == word2) && (index != i) { if len(res) < len(word1) { res = word1 } indicesNext = append(indicesNext, index) } } indicesCurrent = indicesNext indicesNext = []int{} } } return res } func LongestDupSubstringSmartforceMark2(s string) string { strLen := len(s) if strLen < 2 { return "" } indicesNext := []int{} indicesAll := []int{} for j := 0; j < strLen; j++ { indicesAll = append(indicesAll, j) } res := "" for i := 0; i < strLen-len(res); i++ { indicesCurrent := indicesAll for ln := 1; ln <= strLen-i; ln++ { word1 := s[i : i+ln] for _, index := range indicesCurrent { if index+ln > strLen { continue } word2 := s[index : index+ln] if (index != i) && (word1 == word2) { if len(res) < len(word1) { res = word1 } indicesNext = append(indicesNext, index) } } indicesCurrent = indicesNext indicesNext = []int{} } } return res } func LongestDupSubstringBruteforceReversedMark2(s string) string { strLen := len(s) if strLen < 2 { return "" } res := "" for ln := strLen - 1; ln > 0; ln-- { if ln < len(res) { break } for i := 0; i < strLen-ln; i++ { word1 := s[i : i+ln] for j := i + 1; j+ln <= strLen; j++ { word2 := s[j : j+ln] if word1 == word2 { if len(res) < len(word1) { res = word1 } break } } } } return res } func LongestDupSubstringSmartforceMark3(s string) string { strLen := len(s) if strLen < 2 { return "" } indicesNext := []int{} indicesAll := []int{} for j := 0; j < strLen; j++ { indicesAll = append(indicesAll, j) } res := "" for i := 0; i < strLen-len(res); i++ { indicesCurrent := indicesAll[i+1:] for ln := 1; ln <= strLen-i; ln++ { word1 := s[i : i+ln] for _, index := range indicesCurrent { if index+ln > strLen { continue } if s[i+ln-1] == s[index+ln-1] { if len(res) < len(word1) { res = word1 } indicesNext = append(indicesNext, index) } } indicesCurrent = indicesNext indicesNext = []int{} } } return res } func LongestDupSubstringSmartforceMark3Goroutine(s string, from int, to int) string { strLen := len(s) if strLen < 2 { return "" } indicesNext := []int{} indicesAll := []int{} for j := 0; j < strLen; j++ { indicesAll = append(indicesAll, j) } res := "" for i := from; (i < to) && (i < strLen-len(res)); i++ { indicesCurrent := indicesAll[i+1:] for ln := 1; ln <= strLen-i; ln++ { word1 := s[i : i+ln] for _, index := range indicesCurrent { if index+ln > strLen { continue } if s[i+ln-1] == s[index+ln-1] { if len(res) < len(word1) { res = word1 } indicesNext = append(indicesNext, index) } } indicesCurrent = indicesNext indicesNext = []int{} } } return res } func LongestDupSubstringGoroutines(s string) string { threads := 24 results := make([]string, threads) interval := len(s) / threads if interval < (800 / threads) { return LongestDupSubstringSmartforceMark3Goroutine(s, 0, len(s)) } wg := new(sync.WaitGroup) wg.Add(threads) for i := 0; i < threads-1; i++ { go func(input int) { results[input] = LongestDupSubstringSmartforceMark3Goroutine(s, input*interval, input*interval+interval) wg.Done() }(i) } go func(input int) { results[input] = LongestDupSubstringSmartforceMark3Goroutine(s, input*interval, len(s)) wg.Done() }(threads - 1) wg.Wait() resLen := -1 res := "" for _, w := range results { if len(w) > resLen { resLen = len(w) res = w } } return res } func LongestDupSubstring(s string) string { return LongestDupSubstringGoroutines(s) }