Codeforces 138B (226B) Two Strings

問題

二つの文字列s, tが与えられる。
任意のiに対して、sのi番目の文字を含んだ、必ずしも連続しないsの部分文字列であって、
tに一致するものが存在するか。

存在するならYesを、そうでないならNoを出力せよ。

制約条件

s, tの長さ≦2 * 10^5
s, tは英小文字からなる

方針

sのi番目を含む部分文字列でtに一致するものが存在するかを、全てのiについて調べる。
ひとつのiに対するチェックの時間が短ければよい。


sのi番目より左側をtの左側からできるだけマッチさせる。この位置をrとする。
sのi番目より右側をtの右側からできるだけマッチさせる。この位置をlとする。


tの、[l-1, r-1]の範囲にs[i]が一つでも含まれていればよい。


l, rは最初にDPをしておけばよくて、
s[i]がtのある範囲にあるかは、文字ごとに累積和を計算しておけばよい。

ソースコード

const int MX = 200010;
string s, t;
int n, m;
int l[MX], r[MX], sum[MX][26];

int main(){
	cin >> s >> t;
	n = s.size();
	m = t.size();
	
	rep(i, n){
		r[i] = i ? r[i - 1] : -1;
		if(r[i] < m - 1 && t[r[i] + 1] == s[i]) r[i]++;
	}
	l[n] = m;
	for(int i = n - 1; i >= 0; i--){
		l[i] = l[i + 1];
		if(l[i] > 0 && t[l[i] - 1] == s[i]) l[i]--;
	}
	rep(i, m) rep(j, 26){
		sum[i + 1][j] = sum[i][j] + (t[i] == 'a' + j);
	}
	rep(i, n){
		int a = i ? min(m, r[i - 1] + 2) : 1;
		int b = max(0, l[i + 1] - 1);
		int c = s[i] - 'a';
		
		if(sum[a][c] - sum[b][c] <= 0){
			cout << "No" << endl;
			return 0;
		}
	}
	cout << "Yes" << endl;
	return 0;
}