comments | difficulty | edit_url | tags | |||||
---|---|---|---|---|---|---|---|---|
true |
中等 |
|
给定一个 下标从0开始 的字符串 s
,以及一个二维整数数组 queries
,其中 queries[i] = [li, ri]
表示 s
中从索引 li
开始到索引 ri
结束的子串(包括两端),即 s[li..ri]
。
返回一个数组 ans
,其中 ans[i]
是 queries[i]
的 同端 子串的数量。
如果一个 下标从0开始 且长度为 n
的字符串 t
两端的字符相同,即 t[0] == t[n - 1]
,则该字符串被称为 同端。
子串 是一个字符串中连续的非空字符序列。
示例 1:
输入:s = "abcaab", queries = [[0,0],[1,4],[2,5],[0,5]] 输出:[1,5,5,10] 解释:每个查询的同端子串如下: 第一个查询:s[0..0] 是 "a",有 1 个同端子串:"a"。 第二个查询:s[1..4] 是 "bcaa",有 5 个同端子串:"bcaa", "bcaa", "bcaa", "bcaa", "bcaa"。 第三个查询:s[2..5] 是 "caab",有 5 个同端子串:"caab", "caab", "caab", "caab", "caab"。 第四个查询:s[0..5] 是 "abcaab",有 10 个同端子串:"abcaab", "abcaab", "abcaab", "abcaab", "abcaab", "abcaab", "abcaab", "abcaab", "abcaab", "abcaab"。
示例 2:
输入:s = "abcd", queries = [[0,3]] 输出:[4] 解释:唯一的查询是 s[0..3],它有 4 个同端子串:"abcd", "abcd", "abcd", "abcd"。
提示:
2 <= s.length <= 3 * 104
s
仅包含小写英文字母。1 <= queries.length <= 3 * 104
queries[i] = [li, ri]
0 <= li <= ri < s.length
我们可以预处理出每个字母的前缀和,记录在数组
时间复杂度
class Solution:
def sameEndSubstringCount(self, s: str, queries: List[List[int]]) -> List[int]:
n = len(s)
cs = set(s)
cnt = {c: [0] * (n + 1) for c in cs}
for i, a in enumerate(s, 1):
for c in cs:
cnt[c][i] = cnt[c][i - 1]
cnt[a][i] += 1
ans = []
for l, r in queries:
t = r - l + 1
for c in cs:
x = cnt[c][r + 1] - cnt[c][l]
t += x * (x - 1) // 2
ans.append(t)
return ans
class Solution {
public int[] sameEndSubstringCount(String s, int[][] queries) {
int n = s.length();
int[][] cnt = new int[26][n + 1];
for (int j = 1; j <= n; ++j) {
for (int i = 0; i < 26; ++i) {
cnt[i][j] = cnt[i][j - 1];
}
cnt[s.charAt(j - 1) - 'a'][j]++;
}
int m = queries.length;
int[] ans = new int[m];
for (int k = 0; k < m; ++k) {
int l = queries[k][0], r = queries[k][1];
ans[k] = r - l + 1;
for (int i = 0; i < 26; ++i) {
int x = cnt[i][r + 1] - cnt[i][l];
ans[k] += x * (x - 1) / 2;
}
}
return ans;
}
}
class Solution {
public:
vector<int> sameEndSubstringCount(string s, vector<vector<int>>& queries) {
int n = s.size();
int cnt[26][n + 1];
memset(cnt, 0, sizeof(cnt));
for (int j = 1; j <= n; ++j) {
for (int i = 0; i < 26; ++i) {
cnt[i][j] = cnt[i][j - 1];
}
cnt[s[j - 1] - 'a'][j]++;
}
vector<int> ans;
for (auto& q : queries) {
int l = q[0], r = q[1];
ans.push_back(r - l + 1);
for (int i = 0; i < 26; ++i) {
int x = cnt[i][r + 1] - cnt[i][l];
ans.back() += x * (x - 1) / 2;
}
}
return ans;
}
};
func sameEndSubstringCount(s string, queries [][]int) []int {
n := len(s)
cnt := make([][]int, 26)
for i := 0; i < 26; i++ {
cnt[i] = make([]int, n+1)
}
for j := 1; j <= n; j++ {
for i := 0; i < 26; i++ {
cnt[i][j] = cnt[i][j-1]
}
cnt[s[j-1]-'a'][j]++
}
var ans []int
for _, q := range queries {
l, r := q[0], q[1]
ans = append(ans, r-l+1)
for i := 0; i < 26; i++ {
x := cnt[i][r+1] - cnt[i][l]
ans[len(ans)-1] += x * (x - 1) / 2
}
}
return ans
}
function sameEndSubstringCount(s: string, queries: number[][]): number[] {
const n: number = s.length;
const cnt: number[][] = Array.from({ length: 26 }, () => Array(n + 1).fill(0));
for (let j = 1; j <= n; j++) {
for (let i = 0; i < 26; i++) {
cnt[i][j] = cnt[i][j - 1];
}
cnt[s.charCodeAt(j - 1) - 'a'.charCodeAt(0)][j]++;
}
const ans: number[] = [];
for (const [l, r] of queries) {
ans.push(r - l + 1);
for (let i = 0; i < 26; i++) {
const x: number = cnt[i][r + 1] - cnt[i][l];
ans[ans.length - 1] += (x * (x - 1)) / 2;
}
}
return ans;
}
impl Solution {
pub fn same_end_substring_count(s: String, queries: Vec<Vec<i32>>) -> Vec<i32> {
let n = s.len();
let mut cnt: Vec<Vec<i32>> = vec![vec![0; n + 1]; 26];
for j in 1..=n {
for i in 0..26 {
cnt[i][j] = cnt[i][j - 1];
}
cnt[(s.as_bytes()[j - 1] as usize) - (b'a' as usize)][j] += 1;
}
let mut ans: Vec<i32> = Vec::new();
for q in queries.iter() {
let l = q[0] as usize;
let r = q[1] as usize;
let mut t = (r - l + 1) as i32;
for i in 0..26 {
let x = cnt[i][r + 1] - cnt[i][l];
t += (x * (x - 1)) / 2;
}
ans.push(t);
}
ans
}
}