atcoder-solutionsatcoder-solutions
abc452_d

No-Subsequence Substring の解説

解説 by @ohnuma

解説

[l, r)で、含まない部分列が作れた時には、lを固定したとき、ありうるrはr - l個あるので

この前提をもってlを固定してrをできる限り大きくすることを考えます。

Tが小さいのでTに関しては各lの過程で都度考えることができるため、以下のことを操作します。

  • はじめright = l - 1として処理を開始する
  • 文字Tiがright + 1より先ではじめてはじめてTiが出てくるindexをnextとする
    • そのindexが見つからなかった場合はindex = nとして操作を終了する
  • right = nextとする

として繰り返したときが伸ばせる最大のrとして得られます。

よってlを固定した時の部分問題が解けたので各lに対してこの問題をとくことで元の問題に回答できます。

fn main() { input! { s: Chars, t: Chars } let n = s.len(); let alpha = ('a'..='z').collect_vec(); let mut map = vec![BTreeSet::new(); alpha.len()]; for i in 0..n { let idx = alpha.iter().position(|&e| e == s[i]).unwrap(); map[idx].insert(i); } let mut ans = 0; for left in 0..s.len() { let mut right = left; for (i, &c) in t.iter().enumerate() { let idx = alpha.iter().position(|&e| e == c).unwrap(); let search = if i == 0 {right} else {right + 1}; let next = map[idx].range(search..).next(); if let Some(&v) = next { right = v; } else { right = n; break; } } ans += right - left; } println!("{}", ans); }

コメント