B3683 [语言月赛202211] String Problem 题解
B3683 [语言月赛202211] String Problem 题解
Source & Knowledge
2022 年 11 月语言月赛,由洛谷网校入门计划/基础计划提供。
本题考察字符串处理、字符串判等和算法优化能力。
文字题解
题目大意
给定两个字符串
解析
算法一:字符串暴力判等
使用 string 类型读入存储
string s, t;
cin >> s >> t;
判断两个字符串相等只需要使用 == 运算符:
if (s == t) cout << "Yes\n";
else cout << "No\n";
对字符串某位置作出修改,只需要用[] 运算符进行单点修改。需要注意的是,string 的下标范围是
cin >> o >> p >> c;
if (o == 0) s[p - 1] = c;
else t[p - 1] = c;
if (s == t) cout << "Yes\n";
else cout << "No\n";
需要注意的是,每次判断两字符串是否相等的运算量在最坏情况下大约和字符串长度
bool equal(string s, string t) {
if (s.length() != t.length()) return false;
for (int i = 0; i < s.length(); ++i) if (s[i] != t[i]) return false;
return true;
}
而我们一共需要处理大约
算法二:存储不匹配的位置数量
考虑对算法一做出优化。
注意到对于上面的算法,每进行一次修改操作,我们只修改了字符串一位的信息,却把字符串的所有位置都重新比较了一遍。对于没有被修改的位置,我们没有必要去重新比较它们是否相等。
进一步思考发现,对于一次询问,我们也不需要直到它们具体哪一位是不同的,只需要知道他们是否存在不同的位置即可。这启发我们用一个变量
初始输入
for (int i = 0; i < n; ++i) if (s[i] != t[i]) ++cnt;
考虑每次修改某个字符串的某个下标时,其他位置的不同数量不受影响。我们先在
也就是说,在修改前,如果
写作代码就是:
cin >> o >> p >> c;
if (s[p - 1] != t[p - 1]) --cnt; // 去掉 p 这一位置原来对 cnt 的影响
if (o == 0) s[p - 1] = c;
else t[p - 1] = c;
if (s[p - 1] != t[p - 1]) ++cnt; // 加上 p 这一位置修改后对 cnt 的影响
if (cnt == 0) cout << "Yes\n"; // 如果有 0 个位置不同,说明两字符串相等
else cout << "No\n";
这样,每次判等的运算量被我们降低了很多,就可以通过本题了。
注意事项
-
如果使用 char 数组存储字符串,在 for 循环里采取类似
for (int i = 0; i < strlen(s); ++i)的代码会造成超时,因为单次求strlen(s)的运算量大约也是字符串长度。 -
注意本题共有大约
10^6 次输入输出,需要关闭 cin 和 stdio 的同步、和 cout 的绑定,同时使用\n换行才能降低输入输出用时。方法是:在 main 函数开头加入:ios::sync_with_stdio(false); cin.tie(0);并把代码中的
endl全部改为'\n'。详见视频题解。
视频题解
完整代码请在视频中查看。
说明:视频题解中对