公式
F - Error Correction 解説
by
F - Error Correction 解説
by
leaf1415
\(S_i\) が \(T\) と等しい可能性があるか、つまり、\(T \coloneqq S_i\) とおいたとき、問題文中の \(4\) つの条件のいずれかを満たすか判定することを考えます。本問題を解くには各 \(i\) についてこれを行えば良いです。
\(T \coloneqq S_i\) とおきます。
\(T\) と \(T'\) が先頭から見て何文字目まで一致するかを調べ、一致する最大の長さを \(A\) とおきます。
同様に、\(T\) と \(T'\) が末尾から見たときに一致する最大の長さを \(B\) とおきます。
例えば、abcd
と abcdacd
は、先頭から見ると abc
の \(3\) 文字までが一致し、末尾から見ると cd
の \(2\) 文字までが一致します。
このとき、問題文中の \(4\) つの条件はそれぞれ、\(A, B\) および、\(T\) と \(T'\) の長さ \(|T|, |T'|\) によって下記の通りに言い換えられます。
- \(T'\) は \(T\) と等しい:\(A = B = |T| = |T'|\)
- \(T'\) は \(T\) のいずれか \(1\) つの位置(先頭と末尾も含む)に英小文字を \(1\) つ挿入して得られる文字列である:\(A+B \geq |T| = |T'|-1\)
- \(T'\) は \(T\) からある \(1\) 文字を削除して得られる文字列である:\(A+ B \geq |T|-1 = |T'|\)
- \(T'\) は \(T\) からある \(1\) 文字を別の英小文字に変更して得られる文字列である:\(A +B = |T| -1 = |T'| - 1\)
よって、\(A, B, |T|, |T'|\) が上記の \(4\) つのいずれかの条件を満たすかを実際に判定すれば良いです。
以下に、C++ 言語による本問題の正解例を記載します。
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
ll n;
string s[500001], t2;
ll a[500001], b[500001];
ll calc(const string &s, const string &t)
{
for(int i = 0; i < (int)t.size(); i++){
if(i >= s.size()) return s.size();
if(s[i] != t[i]) return i;
}
return t.size();
}
int main(void){
cin >> n >> t2;
for(int i = 1; i <= n; i++) cin >> s[i];
for(int i = 1; i <= n; i++) a[i] = calc(s[i], t2);
reverse(t2.begin(), t2.end());
for(int i = 1; i <= n; i++){
reverse(s[i].begin(), s[i].end());
b[i] = calc(s[i], t2);
}
vector<ll> ans;
for(int i = 1; i <= n; i++){
const string &t = s[i];
bool flag = false;
if(a[i] == t.size() && t.size() == t2.size()) flag = true;
if(a[i]+b[i] >= t.size() && t.size()+1 == t2.size()) flag = true;
if(a[i]+b[i] >= t.size()-1 && t.size()-1 == t2.size()) flag = true;
if(a[i]+b[i] == t.size()-1 && t.size() == t2.size()) flag = true;
if(flag) ans.push_back(i);
}
cout << ans.size() << endl;
for(auto x : ans) cout << x << " ";
cout << endl;
return 0;
}
投稿日時:
最終更新: