codeforces1303C Perfect Keyboard 模拟或判断欧拉路

网址:https://codeforces.com/contest/1303/problem/C

题意:

找出一个每种小写字母出现且只出现一次的字符串,且要符合条件:给出字符串的所有相邻两个字母在构造字符串中也相邻。如果没有输出$NO$。

题解:

解法1:

直接模拟,我们可以先从给出字符串第一个字符开始,初始化一个串只有第一个字符,然后如下构造:对于其下一个字符:如果它已经出现在了构造串中,则$1:$如果相邻的是这个字母,就直接转移。$2:$如果不是,输出$NO$。如果没有出现在构造串中,则$1:$如果当前字符在构造串的最前面,就在其前面加入一个字符,$2:$如果在最后面,就在其后面连接一个字符,$3:$如果在中间,输出“NO”。最后再把没有用上的字符按顺序加进去就可以了。

AC代码:

#include 
using namespace std;
bool f[26];
string s, t;
int solve()
{
	cin >> s;
	t = string(1, s[0]);
	int pos = 0;
	memset(f, 0, sizeof(f));
	f[s[0] - 'a'] = 1;
	for (int i = 1; i < s.size(); ++i)
	{
		if (f[s[i] - 'a'])
		{
			if (pos > 0 && t[pos - 1] == s[i])
				pos -= 1;
			else if (pos < t.size() - 1 && t[pos + 1] == s[i])
				pos += 1;
			else
				return cout << "NO\n", 0;
		}
		else
		{
			if (pos == 0)
				t = s[i] + t;
			else if (pos == t.size() - 1)
				pos += 1, t += s[i];
			else
				return cout << "NO\n", 0;
		}
		f[s[i] - 'a'] = 1;
	}
	for (int i = 0; i < 26; ++i)
		if (!f[i])
			t += (i + 'a');
	cout << "YES\n" << t << '\n';
	return 0;
}
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	int T;
	cin >> T;
	while (T--)
		solve();
	return 0;
}

 解法2:

我们可以知道,从一个字符转移到另一个字符相当于是建立一条从起点到终点的有向边,所以直接用set对字符串建无向图,寻找一条欧拉路即可。如果出现度数大于3的结点,或者出现环,比如$“ABCA”$,就输出$NO$,(这个条件容易漏),特判长度是$1$的。然后从度为$1$的结点$dfs$最后把剩下没有选上的的输出就行了。

AC代码:

#include 
using namespace std;
const int N = 2e2 + 5, M = 26;
setG[M];
bool vis[M];
char s[N];
void dfs(int u, int f)
{
	if (vis[u])
		return;
	vis[u] = 1;
	putchar(u + 'a');
	for (auto i : G[u])
		dfs(i, u);
}
int solve()
{
	scanf("%s", s);
	memset(vis, 0, sizeof(vis));
	int len = strlen(s);
	if (len == 1)
		return printf("YES\nabcdefghijklmnopqrstuvwxyz\n"), 0;
	for (int i = 0; i < M; ++i)
	{
		G[i].clear();
		vis[i] = 0;
	}
	for (int i = 1; i < len; ++i)
	{
		G[s[i] - 'a'].insert(s[i - 1] - 'a');
		G[s[i - 1] - 'a'].insert(s[i] - 'a');
	}
	int cnt1 = 0, rt;
	for (int i = 0; i < M; ++i)
	{
		if (G[i].size() > 2)
			return printf("NO\n"), 0;
		else if (G[i].size() == 1)
			++cnt1, rt = i;
	}
	if (cnt1 != 2)
		return printf("NO\n"), 0;
	printf("YES\n");
	dfs(rt, -1);
	for (int i = 0; i < M; ++i)
		dfs(i, -1);
	return printf("\n"), 0;
}
int main()
{
	int t;
	scanf("%d", &t);
	while (t--)
		solve();
	return 0;
}

 

你可能感兴趣的:(codeforces1303C Perfect Keyboard 模拟或判断欧拉路)