1. 问题描述:
给定 n 个字符串 f1,f2,…,fn,这些字符串两两不同,下面给定 q 个询问,其中,第 i 次询问给定一个字符串 si,你的任务是:
计算 f1∼fn 这 n 个字符串中,包含 si 作为子串的字符串的数量;
从 f1∼fn 这 n 个字符串中,任选一个包含 si 作为子串的字符串输出;
输入格式
第一行包含整数 n,接下来 n 行,其中第 i 行包含字符串 fi。再一行包含整数 q。接下来 q 行,其中第 i 行包含字符串 si,所有 fi 和 si 都只包含小写字母、数字以及 .
输出格式
共 q 行,其中第 i 行输出第 i 个询问的答案,首先输出 f1∼fn 这 n 个字符串中包含 si 作为子串的字符串的数量,然后从 f1∼fn 这 n 个字符串中任选一个包含 si 作为子串的字符串输出。如果这样的字符串不唯一,则输出任意合理字符串均可,如果这样的字符串不存在,则输出 -。
数据范围
前三个测试点满足 1 ≤ n,q ≤ 20;
所有测试点满足 1 ≤ n ≤ 10000,1 ≤ q ≤ 50000,1 ≤ |fi|,|si| ≤ 8;
输入样例:
4
test
contests
test.
.test
6
ts
.
st.
.test
contes.
st
输出样例:
1 contests
2 .test
1 test.
1 .test
0 -
4 test.
来源:https://www.acwing.com/problem/content/description/4401/
2. 思路分析:
分析题目可以知道每一个 fi 和 si 的长度满足:1 <= |fi|,|si| ≤ 8,所以字符串的长度是非常短的,那么子串的数目相对就比较少,对于一个长度为 8 的字符串对应的子串数目为 (1 + 8) * 8 / 2 = 36,一共有 10000 个 f 字符串,所以总共的子串数目为 36 w,我们可以开一个哈希表来存储这些子串,时间复杂度大概为:360000 * 8 = 2880000 是可以通过的;由于需要输出包含子串 si 的 fi 的字符串数量,并且需要输出包含 si 对应的 fi,所以至少需要开两个哈希表,其中哈希表 count 用来记录子串 si 在 fi 中出现的次数,哈希表 mp 用来记录子串 si 对应的字符串 fi,并且每一个 fi 对应的子串 s 可能是重复的所以需要开一个哈希表 S 用来去重,存储 fi 中所有不重复子串。
3. 代码如下:
python:
class Solution:
def process(self):
n = int(input())
count, mp = dict(), dict()
i = 0
while n > 0:
s = input()
# S用来去重
S = set()
for i in range(len(s)):
# s1 拼接所有的子串
s1 = ""
for j in range(i, len(s)):
s1 += s[j]
S.add(s1)
# 枚举 s 中的所有子串
for x in S:
if x not in count:
count[x] = 1
else:
count[x] += 1
# mp 用来记录字串对应的其中一个字符串
mp[x] = s
n -= 1
m = int(input())
for i in range(m):
s = input()
if s in mp:
print(count[s], mp[s])
else:
print(0, "-")
if __name__ == "__main__":
Solution().process()
go:
package main
import (
"bufio"
"fmt"
"io"
"os"
)
func run(r io.Reader, w io.Writer) {
// 使用bufio.NewReader()优化输入输出数据的效率
in := bufio.NewReader(r)
out := bufio.NewWriter(w)
// 将缓存输出写入到标准输出中
defer out.Flush()
var (
n, m int
s string
)
fmt.Fscan(in, &n)
count := make(map[string]int)
// mp 记录子串对应的字符串
mp := make(map[string]string)
for k := 0; k < n; k++ {
fmt.Fscan(in, &s)
// S 用来去重
S := make(map[string]int)
// 拼接 s 中的所有子串
for i := 0; i < len(s); i++ {
s1 := ""
for j := i; j < len(s); j++ {
s1 += string(s[j])
S[s1] = 1
}
}
// 遍历哈希表
for key := range S {
count[key] += 1
mp[key] = s
}
}
// m 个询问
fmt.Fscan(in, &m)
for i := 0; i < m; i++ {
fmt.Fscan(in, &s)
v, flag := mp[s]
if flag {
fmt.Fprintln(out, count[s], v)
} else {
fmt.Fprintln(out, 0, "-")
}
}
}
func main() {
run(os.Stdin, os.Stdout)
}