题目3 : 字符替换
描述
给定一个只包含小写字母的初始字符串S,以及N个操作。每个操作都是把当前字符串中所有的字符Xi替换成字符Yi (Xi, Yi是一个小写字母),上一个操作的结果是下一个操作的对象。
现在小Hi要对初始字符串完成所有N个操作,不过他可以任意安排N个操作的顺序。他希望最终得到的字符串中有最多的'h'字符。请你算出最多能得到多少个'h'字符。
输入
第一行包含一个整数N。
第二行包含一个小写字符串S。
以下N行每行包含2个字符Xi和Yi。
1 <= N <= 1000
1 <= |S| <= 100000
输出
一个整数代表答案。
样例输入
2 aabb b h a b
样例输出
4
思路:这道题刚开始我没注意到要每个序列都执行,导致写的不对,后来发现了,想了半天看了别人的代码懂了,其实这道题就是判断有没有环有环结果不同,没环减去h变成其它字符的个数就好,有环直接输出。
代码:
#include<iostream>
#include<cstdio>
#include<map>
#include<vector>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;
const int maxn=1e5+100;
int vis[30];
int mp[30][30];
int cnt[30];
char s[maxn];
int ans=0;
vector<int>st;
void dfs(int id)
{
ans+=cnt[id];
vis[id]=1;
for(int i=0;i<26;i++)
{
if(mp[i][id]&&!vis[i])
{
dfs(i);
}
}
return ;
}
int main()
{
int n;
scanf("%d",&n);
scanf("%s",s);
int len=strlen(s);
for(int i=0;i<len;i++)
{
cnt[s[i]-'a']++;
}
for(int i=1;i<=n;i++)
{
char a[3],b[3];
scanf("%s%s",a,b);
int c=a[0]-'a';
int d=b[0]-'a';
mp[c][d]=1;
if(c==('h'-'a'))
{
st.push_back(d);
}
}
int h='h'-'a';
dfs(h);
int flag=0;
for(int i=0;i<st.size();i++)
{
if(vis[st[i]])
{
flag=1;//如果有环 例如 h-a a-h h-b 你可以先执行 h-a 再执行 a-h h-b自然无效
}
}
if(!flag&&st.size()>0)
{
ans-=cnt[h];
}
printf("%d\n",ans);
return 0;
}