列表

详情


100212. 统计前后缀下标对 I

给你一个下标从 0 开始的字符串数组 words

定义一个 布尔 函数 isPrefixAndSuffix ,它接受两个字符串参数 str1str2

例如,isPrefixAndSuffix("aba", "ababa") 返回 true,因为 "aba" 既是 "ababa" 的前缀,也是 "ababa" 的后缀,但是 isPrefixAndSuffix("abc", "abcd") 返回 false

以整数形式,返回满足 i < jisPrefixAndSuffix(words[i], words[j])true 的下标对 (i, j) 数量

 

示例 1:

输入:words = ["a","aba","ababa","aa"]
输出:4
解释:在本示例中,计数的下标对包括:
i = 0 且 j = 1 ,因为 isPrefixAndSuffix("a", "aba") 为 true 。
i = 0 且 j = 2 ,因为 isPrefixAndSuffix("a", "ababa") 为 true 。
i = 0 且 j = 3 ,因为 isPrefixAndSuffix("a", "aa") 为 true 。
i = 1 且 j = 2 ,因为 isPrefixAndSuffix("aba", "ababa") 为 true 。
因此,答案是 4 。

示例 2:

输入:words = ["pa","papa","ma","mama"]
输出:2
解释:在本示例中,计数的下标对包括:
i = 0 且 j = 1 ,因为 isPrefixAndSuffix("pa", "papa") 为 true 。
i = 2 且 j = 3 ,因为 isPrefixAndSuffix("ma", "mama") 为 true 。
因此,答案是 2 。

示例 3:

输入:words = ["abab","ab"]
输出:0
解释:在本示例中,唯一有效的下标对是 i = 0 且 j = 1 ,但是 isPrefixAndSuffix("abab", "ab") 为 false 。
因此,答案是 0 。

 

提示:

原站题解

去查看

上次编辑到这里,代码来自缓存 点击恢复默认模板
class Solution { public: int countPrefixSuffixPairs(vector<string>& words) { } };

python3 解法, 执行用时: 40 ms, 内存消耗: 16.5 MB, 提交时间: 2024-02-19 09:57:25

class Node:
    __slots__ = 'son', 'cnt'

    def __init__(self):
        self.son = dict()
        self.cnt = 0

class Solution:
    def countPrefixSuffixPairs(self, words: List[str]) -> int:
        ans = 0
        root = Node()
        for t in words:
            z = self.calc_z(t)
            cur = root
            for i, c in enumerate(t):
                if c not in cur.son:
                    cur.son[c] = Node()
                cur = cur.son[c]
                if z[-1 - i] == i + 1:  # t[-1-i:] == t[:i+1]
                    ans += cur.cnt
            cur.cnt += 1
        return ans

    def calc_z(self, s: str) -> List[int]:
        n = len(s)
        z = [0] * n
        l, r = 0, 0
        for i in range(1, n):
            if i <= r:
                z[i] = min(z[i - l], r - i + 1)
            while i + z[i] < n and s[z[i]] == s[i + z[i]]:
                l, r = i, i + z[i]
                z[i] += 1
        z[0] = n
        return z

golang 解法, 执行用时: 3 ms, 内存消耗: 5.1 MB, 提交时间: 2024-02-19 09:55:56

// Z函数 + 字典树
func calcZ(s string) []int {
	n := len(s)
	z := make([]int, n)
	l, r := 0, 0
	for i := 1; i < n; i++ {
		if i <= r {
			z[i] = min(z[i-l], r-i+1)
		}
		for i+z[i] < n && s[z[i]] == s[i+z[i]] {
			l, r = i, i+z[i]
			z[i]++
		}
	}
	z[0] = n
	return z
}

func countPrefixSuffixPairs(words []string) (ans int) {
	type node struct {
		son [26]*node
		cnt int
	}
	root := &node{}
	for _, t := range words {
		z := calcZ(t)
		cur := root
		for i, c := range t {
			c -= 'a'
			if cur.son[c] == nil {
				cur.son[c] = &node{}
			}
			cur = cur.son[c]
			if z[len(t)-1-i] == i+1 { // t[:i+1] == t[len(t)-1-i:]
				ans += cur.cnt
			}
		}
		cur.cnt++
	}
	return
}

golang 解法, 执行用时: 6 ms, 内存消耗: 4.4 MB, 提交时间: 2024-02-19 09:54:11

func countPrefixSuffixPairs(words []string) (ans int) {
	type pair struct{ x, y byte }
	type node struct {
		son map[pair]*node
		cnt int
	}
	root := &node{son: map[pair]*node{}}
	for _, s := range words {
		cur := root
		for i := range s {
			p := pair{s[i], s[len(s)-1-i]}
			if cur.son[p] == nil {
				cur.son[p] = &node{son: map[pair]*node{}}
			}
			cur = cur.son[p]
			ans += cur.cnt
		}
		cur.cnt++
	}
	return
}

python3 解法, 执行用时: 44 ms, 内存消耗: 16.5 MB, 提交时间: 2024-02-19 09:50:21

# 字典树, __slots__定义的属性仅对当前类示例起限制作用,对继承的子类是不起限制作用
class Node:
    __slots__ = 'son', 'cnt'

    def __init__(self):
        self.son = dict()
        self.cnt = 0

class Solution:
    def countPrefixSuffixPairs(self, words: List[str]) -> int:
        ans = 0
        root = Node()
        for s in words:
            cur = root
            for p in zip(s, reversed(s)):
                if p not in cur.son:
                    cur.son[p] = Node()
                cur = cur.son[p]
                ans += cur.cnt
            cur.cnt += 1
        return ans

python3 解法, 执行用时: 43 ms, 内存消耗: 16.5 MB, 提交时间: 2024-02-19 09:45:04

class Solution:
    def countPrefixSuffixPairs(self, words: List[str]) -> int:
        c = Counter()
        ans = 0
        for w in words:
            for k, v in c.items():
                if w.startswith(k) and w.endswith(k):
                    ans += v
            c[w] += 1
        return ans

上一题