题意:
输入 字母(用变量名 AA 代替) n
// 分别代表这个串中最大的字母(这个是按照原有字母表的顺序确定的) 、 n个串
按照 新规定字母表的大小顺序 给出由小到大排序好的 n 个字符串,求 a - AA 之间的由小到大的新顺序
思路:
每相邻两行进行比较该列字母的大小
遇到当前比较的两个字母不同时,用 ch[i][j] 标记一下,表示第i行与第j行不能继续比较了
用邻接矩阵存图,进行拓扑排序
如果 a---->b && b -----> a同时成立,则输出 "IMPOSSIBLE" ,自相矛盾,根本不可能
如果存在多个入度为0的点,代表结果不唯一,则输出 "AMBIGUOUS"
否则输出唯一确定的答案
例样例1
d 4 cab cda ccc badca求 a - d 之间字母的新顺序
由第一列可以知 c < b
由第二列知: a < d a < c d < c (可以比较的前提是 前一个字母必须相同)
利用拓扑排序画出有向图,根据拓扑排序原理可以得出新顺序是 adcb
CODE :
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#define memset(a,n) memset(a,n,sizeof(a))
#define INF 0x3f3f3f3f
using namespace std;
typedef long long LL;
const LL MAXX = 1e3+10;
string s[MAXX];
int ch[MAXX][MAXX]; // 标记数组
int mp[200][200]; // 存图
int in[100]; // 入度
char ans[100]; // 结果数组
int main()
{
int n,maxx = -1;
char l;
memset(mp,0);
cin >> l >> n;
for(int i=0; i<n; i++){
cin >> s[i];
int len = s[i].size();
if(len > maxx)
maxx = len; // 记录列的最大值
}
memset(in,0);
memset(ch,0);
int flag = 0;
for(int j=0; j<maxx; j++){
for(int i=1; i<n; i++){
if(ch[i][i-1] == 0){ // 如果第i行可以与第i-1行比较,则继续
if(s[i][j] != s[i-1][j]){ // 如果当前两个字母不相同,则需要标记ch[][]
ch[i][i-1] = 1;
if(mp[s[i][j]][s[i-1][j]] == 1){ // 判断矛盾的情况
flag = 1;
break;
}
mp[s[i-1][j]][s[i][j]] = 1;
}
}
}
if(flag)
break;
}
if(flag){
cout << "IMPOSSIBLE" << endl;
return 0;
}
// Floyd
for(char k='a'; k<=l; k++){
for(char i='a'; i<=l; i++){
for(char j='a'; j<=l; j++){
if(mp[i][k] == 1 && mp[k][j] == 1){
if(mp[j][i] == 1){ // 判断矛盾的情况
flag = 1;
break;
} else {
mp[i][j] = 1;
}
}
}
if(flag)
break;
}
if(flag)
break;
}
if(flag){
cout << "IMPOSSIBLE" << endl;
return 0;
}
// 统计入度
for(char i='a'; i<=l; i++){
for(char j='a'; j<=l; j++){
if(mp[i][j] == 1 && mp[j][i] == 0 && i!=j)
in[j]++;
}
}
// 判断结果的唯一性
int cnt = 0;
while(1){
int sum = 0;
char c;
for(char i='a'; i<=l; i++){
if(in[i] == 0){
sum++;
c = i;
}
}
// 不存在入度为0 的点,存在环,矛盾
if(sum == 0){
cout << "IMPOSSIBLE" << endl;
break;
}
// 多个入度为0的点,结果不确定,结果不唯一
else if(sum > 1){
cout << "AMBIGUOUS" << endl;
break;
}
ans[cnt++] = c;
in[c] = -1; // 标记为 -1,区分其他入度为0的点
if(cnt == l-'a'+1)
break;
// 与c相关的点的入度减1
for(char i='a'; i<=l; i++){
if(mp[c][i] == 1)
in[i]--;
}
}
for(int i=0; i<cnt; i++)
cout << ans[i];
cout << endl;
}