2021-08-16:回文对。给定一组 互不相同 的单词, 找出所有 不同 的索引对 (i, j),使得列表中的两个单词, words[i] + words[j] ,可拼接成回文串。

Posted 福大大架构师每日一题

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021-08-16:回文对。给定一组 互不相同 的单词, 找出所有 不同 的索引对 (i, j),使得列表中的两个单词, words[i] + words[j] ,可拼接成回文串。相关的知识,希望对你有一定的参考价值。

2021-08-16:回文对。给定一组 互不相同 的单词, 找出所有 不同 的索引对 (i, j),使得列表中的两个单词, words[i] + words[j] ,可拼接成回文串。

福大大 答案2021-08-16:

k是字符串长度。
1.依次遍历,嵌套循环。
时间复杂度:O((N^2)k)
2.b逆序+a+b,a+b+a逆序。注意去重。
时间复杂度:O(N
(k^2))。

代码用golang编写。代码如下:

package main

import "fmt"

func main() {
    words := []string{"bat", "tab", "cat"}
    ret := palindromePairs(words)
    fmt.Println(ret)
}

func palindromePairs(words []string) [][]int {
    wordset := make(map[string]int)
    for i := 0; i < len(words); i++ {
        wordset[words[i]] = i
    }
    res := make([][]int, 0)
    //{ [6,23] 、 [7,13] }
    for i := 0; i < len(words); i++ {
        // i words[i]
        // findAll(字符串,在i位置,wordset) 返回所有生成的结果返回
        findRet := findAll(words[i], i, wordset)
        res = append(res, findRet...)
    }
    return res
}

func findAll(word string, index int, words map[string]int) [][]int {
    res := make([][]int, 0)
    reverse := reverse(word)
    rest, ok := words[""]
    if ok && rest != index && word == reverse {
        addRecord(&res, rest, index)
        addRecord(&res, index, rest)
    }
    rs := manacherss(word)
    mid := len(rs) >> 1
    for i := 1; i < mid; i++ {
        if i-rs[i] == -1 {
            ok2 := false
            rest, ok2 = words[reverse[0:mid-i]]
            if ok2 && rest != index {
                addRecord(&res, rest, index)
            }
        }
    }
    for i := mid + 1; i < len(rs); i++ {
        if i+rs[i] == len(rs) {
            ok3 := false
            aaa := reverse[(mid<<1)-i:]
            rest, ok3 = words[aaa]
            if ok3 && rest != index {
                addRecord(&res, index, rest)
            }
        }
    }
    return res
}

func addRecord(res *[][]int, left int, right int) {
    newr := make([]int, 0)
    newr = append(newr, left)
    newr = append(newr, right)
    *res = append(*res, newr)
}

func manacherss(word string) []int {
    mchs := manachercs(word)
    rs := make([]int, len(mchs))
    center := -1
    pr := -1
    for i := 0; i != len(mchs); i++ {
        if pr > i {
            rs[i] = getMin(rs[center<<1-i], pr-i)
        } else {
            rs[i] = 1
        }
        for i+rs[i] < len(mchs) && i-rs[i] > -1 {
            if mchs[i+rs[i]] != mchs[i-rs[i]] {
                break
            }
            rs[i]++
        }
        if i+rs[i] > pr {
            pr = i + rs[i]
            center = i
        }
    }
    return rs
}

func getMin(a int, b int) int {
    if a < b {
        return a
    } else {
        return b
    }
}

func twoSelectOne(c bool, a int, b int) int {
    if c {
        return a
    } else {
        return b
    }
}

func manachercs(word string) string {
    chs := []byte(word)
    mchs := make([]byte, len(chs)*2+1)
    index := 0
    for i := 0; i != len(mchs); i++ {
        if (i & 1) == 0 {
            mchs[i] = '#'
        } else {
            mchs[i] = chs[index]
            index++
        }
    }
    return string(mchs)
}

func reverse(str string) string {
    chs := []byte(str)
    l := 0
    r := len(chs) - 1
    for l < r {
        tmp := chs[l]
        chs[l] = chs[r]
        l++
        chs[r] = tmp
        r--
    }
    return string(chs)
}

执行结果如下:


左神java代码

以上是关于2021-08-16:回文对。给定一组 互不相同 的单词, 找出所有 不同 的索引对 (i, j),使得列表中的两个单词, words[i] + words[j] ,可拼接成回文串。的主要内容,如果未能解决你的问题,请参考以下文章

CF1111E Tree

在给定一组地理坐标的情况下获取友好的位置名称?

砍树

回文数

给定一组顶点,如何生成具有接近最少边数的强连通有向图?

给定一组条件,通过算法确定只有一个条件为真