You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

71 lines
2.6 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include <iostream>
#include <vector>
#include <cstring>
#include <string>
using namespace std;
const int N = 500010;
int p[N]; // 并查集数组
int d[N]; // 度
char str1[15], str2[15]; // 两个字符串
// int b[N]; // 记录字符串(对应的HASH值)是否出现过,是桶的概念
int id[N], n; // 用于离散化根据p是否出现决定是否为其分配新的节点编号有旧的使旧的有新的创建后使新的
int idx; // 创建Trie树时的游标
int tr[N][26]; // Trie树
/*
如果平均字符串长度是10那么在最坏的情况下Trie树中最多可能有500000 * 10 = 5000000个节点。
这是因为在最坏的情况下每个字符串都不共享任何前缀因此每个字符串的每个字符都会在Trie树中创建一个新的节点。
需要注意的是这是一个上界实际的节点数量可能会少于这个值因为许多字符串可能会共享一些前缀这些前缀在Trie树中只会被存储一次。
*/
int insert(string str) { // 插入字典树并返回结尾字符节点编号
int p = 0;
for (int i = 0; i < str.size(); i++) {
int u = str[i] - 'a'; // 映射成0~25,本题只有小写字母
if (!tr[p][u]) tr[p][u] = ++idx;
p = tr[p][u];
}
/* 如上面的论述结果idx:Trie树中有很多的节点,可每个字符串最后的终点只有1个
我们需要知道我们在心中创建的图有多少个节点一般用n表示如果我们直接使用Trie树中的p,虽然在数据范围内不会越界但在1~p之间肯定存在无效的节点这是我们不能接受的
办法就是直接离散化,只保留有用的节点,重新编号:id[N]+cnt
*/
if (!id[p]) id[p] = ++n; // 节点编号
return id[p];
}
// 并查集
int find(int x) {
if (x == p[x]) return x;
return p[x] = find(p[x]);
}
int main() {
#ifndef ONLINE_JUDGE
freopen("POJ2513.in", "r", stdin);
#endif
for (int i = 0; i < N; i++) p[i] = i;
while (~scanf("%s%s", str1, str2)) {
int a = insert(str1), b = insert(str2); // 利用Trie树找出字符串的HASH值,其它与纯字符串131进制的代码一致
d[a]++, d[b]++;
if (find(a) != find(b)) p[find(a)] = find(b);
}
int odd = 0, cnt = 0;
for (int i = 1; i <= n; i++) {
if (p[i] == i) cnt++;
if (d[i] % 2) odd++;
}
int flag = 1;
if ((odd != 0 && odd != 2) || cnt != 1) flag = 0;
if (n == 0) flag = 1;
if (flag)
puts("Possible");
else
puts("Impossible");
return 0;
}