hihoCoder #1902 字符替换
解法
这题比赛时过的人很多,我却没思路,糊里糊涂写了个强联通分量,得了 80 分。
这题思路是这样的。
一个替换操作可以看做一个有向边,所以题目实际上给出了一个有向图 $G$,一个节点代表一个字母。
注意题目要求每个操作都必须执行一次。
关于自环
首先注意到自环是没有意义的,因此处理输入时把自环忽略掉。
这里需要特别说明自环的问题,题目描述中并没有说明 $X_i \ne Y_i$。不过似乎可以合理地假设输入中不存在 $X_i = Y_i$ 的操作。
有些 AC 的代码并没有判断自环,比如冰心水蜜桃的提交。当输入中有自环时,这个代码是有 BUG 的。
关于重边
实际上重边也是没有意义的,但是我们不必特别处理它。
用 $\mathsf{h}$ 表示 $G$ 中对应于字符 ‘h’ 的节点。
设字符 $x$ 在串 $S$ 中出现过且 $x$ 不是 ‘h’ 将 $x$ 出现的次数记做 $c_x$ 。则这 $c_x$ 个 $x$ 能转变为 ‘h’ 的充要条件是「图 $G$ 中存在一条从 $x$ 到 ‘h’ 的简单路径」。
证明:不失一般性,设 $x\to x_1 \to x_2 \to \mathsf{h}$ 是一条从 $x$ 到 ‘h’ 的简单路径,则我们可以按下述方法将 $x$ 变为 ‘h’。
首先将 $x$ 变为 $x_1$,这个操作用掉了 $(x\to x_1)$ 这条边;再将剩下的从 $x$ 发出的边全部用掉,这些边将不换改变当前的字符串,然后把所有从 $x$ 发出的边从图 $G$ 中删除。以此类推。
不难注意到若 ‘h’ 有出边,则上述论证是有问题的。
‘h’ 的出度为零的情形是平凡的。考虑 ‘h’ 的出度不为零的情形。此时若图 $G$ 中不存在「从 ‘h’ 到 ‘h’ 的回路」,则若初始字符串 $S$ 中有 ‘h’,则这些 ‘h’ 终将变成别的字符。因此在这种情况下我们可以将 ‘h’ 的所有出边先执行一遍,并把这些边从图 $G$ 中删除。
这样就完成了上述论证。
不过至此我们只是针对一个字符 $x$ 进行论证。实际上对多个字符,结论是一样的,证明留给读者。
现在来考虑图 $G$ 中存在从 ‘h’ 到 ‘h’ 的回路的情形。注意这样的回路一定不是自环。任取一个从 ‘h’ 到 ‘h’ 的回路 $C$,我们可以先把 'h' 变成回路 $C$ 上 'h' 的后继,得到一个新字符串 $S'$,并把图 $G$ 中其他的 ‘h’ 的出边删除。这样就把问题规约为上一段所描述的情形。
实现
我们需要判断的是,对于字符 $x\in S$ 且 $x\ne\mathsf{h}$,图 $G$ 中是否有一条从 $x$ 到 $\mathsf{h}$ 的简单路径,这可以通过 DFS 完成。另外当 $\mathsf{h}$ 的出度不为零时我们需要判断图 $G$ 中是否存在一条从 $\mathsf{h}$ 到 $\mathsf{h}$ 的回路。先进行DFS,确保字符串 $S$ 中所有字符都被访问过。遍历每一条以 $\mathsf{h}$ 为起点的边 $(\mathsf{h} \to x)$,判断图 $G$ 中是否存在从 $x$ 到 $\mathsf{h}$ 的简单路径。
也可以把边反向以后建图,这样只要对 $\mathsf{h}$ 调用一次 DFS 就可以了。
Implementation
#include <bits/stdc++.h>
using namespace std;
int main() {
//freopen("main.in", "r", stdin);
int n; cin >> n;
string s; cin >> s;
vector<int> cnt(26);
for(auto ch: s) cnt[ch-'a']++;
vector<vector<int>> g(26);
vector<bool> to_h(26);
bool flag = false;
while (n--) {
char x, y; cin >> x >> y;
if (x != y) {
g[y-'a'].push_back(x-'a');
if(x == 'h') {
to_h[y-'a'] = true;
flag = true;
}
}
}
function<void(int)> dfs;
vector<bool> vis(26);
dfs = [&](int u) {
vis[u] = true;
for(auto v: g[u]) {
if(!vis[v]) dfs(v);
}
};
int h = 'h' - 'a';
dfs(h);
int ans = 0;
for (int i = 0; i < 26; i++)
if(vis[i]) ans += cnt[i];
if (flag) {
for (int i = 0; i < 26; i++)
if (to_h[i] && vis[i]) {
flag = false;
break;
}
if (flag) ans -= cnt[h];
}
cout << ans << endl;
return 0;
}
hihoCoder #1902 字符替换的更多相关文章
- strtr和str_replace字符替换函数
(一)strtr是字符替换函数 (1)单个字符替换: <?php echo strtr("abba", "ab", "10"),&qu ...
- AC日记——字符替换 openjudge 1.7 08
08:字符替换 总时间限制: 1000ms 内存限制: 65536kB 描述 把一个字符串中特定的字符全部用给定的字符替换,得到一个新的字符串. 输入 只有一行,由一个字符串和两个字符组成,中间用 ...
- SQL 字符替换
--匹配所有字符替换 )),'被替换','替换') --匹配给定位子替换 update 表名 set 列=stuff(列名,从一开始数位数,往后数几位,替换)
- Oracle的字符替换函数translate用法
参考文档如下:http://www.banping.com/2009/05/18/oracle_function_translate/ Oracle提供了一个字符替换函数translate,不同于re ...
- R语言实现两文件对应行列字符替换(解决正负链统一的问题)
假设存在文件file1.xlsx,其内容如下: 存在文件file2.xlsx,其内容如下: 现在我想从第七列开始,将file2所有的字符替换成file1一样的,即第七.八.九.十列不需要改变,因为fi ...
- Python replace() 和 re.sub() 字符串字符替换
Python replace() 和 re.sub() 字符串字符替换 replace() testStr = 'aa:bb[cc' testStr.replace(':','_') 每次只能替换一个 ...
- js中字符替换函数String.replace()使用技巧
定义和用法 replace() 方法用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串. 语法 stringObject.replace(regexp/substr,replac ...
- PHP基础--strtr和str_replace字符替换函数
(一)strtr是字符替换函数 (1)单个字符替换: <?php echo strtr("abba", "ab", "10"),&qu ...
- C# Replace字符替换函数
它可以将字串内的字符替换为别的字符,可以嵌套使用,如下: 需要注意的是,它可以把字符替换为空,但不可以替换空字符,当不确定字符串是否为空时,可以进行以下判断,再替换: 示例的完整代码: string ...
随机推荐
- JS - 把类似document.querySelectorAll(".xxx")、document.getElementsByName("xxx")这种方法的返回结果转换成数组对象
var btns = document.querySelectorAll(".btn");console.log(btns instanceof Array); // falseb ...
- 执行pip命令时遇到 Fatal error in launcher: Unable to create process using '"'
电脑同时安装了python-2.7.13跟python-3.6.1,安装时勾选了pip,环境变量也已经配置好. 为了方便运行,同时修改了可执行文件为 python2和python3.此时在cmd命令行 ...
- linux系统ext文件系统知识
ext2文件系统细节 我们都知道,操作系统中的数据分为文件内容和文件属性两部分,其中文件内容就是文件的实体数据,而文件属性就是文件类型.权限.属主.修改时间等信息.操作系统会将上述文件的内容放入磁盘文 ...
- 【Mysql】给mysql配置远程登录
grant all privileges on 库名.表名 to '用户名'@'IP地址' identified by '密码' with grant option; flush privileges ...
- strak组件(10):批量操作
效果图: 批量删除只是一个例子,可以根据需求定制自己想要的批量操作. 新增函数 def get_action_list(self) 钩子方法,获取要处理的批量操作的函数 def action_mult ...
- POJ:3268-Silver Cow Party
Silver Cow Party Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 26184 Accepted: 11963 De ...
- css媒体类型
all 用于所有的媒体设备. aural 用于语音和音频合成器. braille 用于盲人用点字法触觉回馈设备. embossed 用于分页的盲人用点字法打印机. handheld 用于小的手持的设备 ...
- jQuery的.on方法
jQuery on()方法是官方推荐的绑定事件的一个方法. $(selector).on(event,childSelector,data,function,map)由此扩展开来的几个以前常见的方法有 ...
- mybatis异常:There is no getter for property named 'xxx' in 'xxx'
在使用mybatis查询的时候出现了下面的异常: org.apache.ibatis.reflection.ReflectionException: There is no getter for pr ...
- Hyper-V中的Linux无法配置网络地址的解决办法
一周碰到2次在Hyper-V 2012中安装了Linux,也安装了IC 3.4.但是却无法配置IP地址的问题.因此造成很多不便,因此找机会把这个原因和解决办法进行了尝试. 这过程中感谢同事的提示,让我 ...