1008. Translations
Constraints
Time Limit: 1 secs, Memory Limit: 32 MB
Description
Bob Roberts is in charge of performing translations of documents between various languages. To aid him in this endeavor his bosses have provided him with translation files. These files come in twos -- one containing sample phrases in one of the languages and the other containing their translations into the other language. However, some over-zealous underling, attempting to curry favor with the higher-ups with his initiative, decided to alphabetically sort the contents of all of the files, losing the connections between the phrases and their translations. Fortunately, the lists are comprehensive enough that the original translations can be reconstructed from these sorted lists. Bob has found this is most usually the case when the phrases all consist of two words. For example, given the following two lists: Language 1 Phrases Language 2 Phrases arlo zym bus seat flub pleve bus stop pleve dourm hot seat pleve zym school bus Bob is able to determine that arlo means hot, zym means seat, flub means school, pleve means bus, and dourm means stop. After doing several of these reconstructions by hand, Bob has decided to automate the process. And if Bob can do it, then so can you.
Input
Input will consist of multiple input sets. Each input set starts with a positive integer n, n 250, indicating the number of two-word phrases in each language. This is followed by 2n lines, each containing one two-word phrase: the first n lines are an alphabetical list of phrases in the first language, and the remaining n lines are an alphabetical list of their translations into the second language. Only upper and lower case alphabetic characters are used in the words. No input set will involve more than 25 distinct words. No word appears as the first word in more than 10 phrases for any given language; likewise, no word appears as the last word in more than 10 phrases. A line containing a single 0 follows the last problem instance, indicating end of input.
Output
For each input set, output lines of the form word1/word2 where word1 is a word in the first language and word2 is the translation of word1 into the second language, and a slash separates the two. The output lines should be sorted according to the first language words, and every first language word should occur exactly once. There should be no white space in the output, apart from a single blank line separating the outputs from different input sets. Imitate the format of the sample output, below. There is guaranteed to be a unique correct translation corresponding to each input instance.
Sample Input
4 arlo zym flub pleve pleve dourm pleve zym bus seat bus stop hot seat school bus 2 iv otas otas re ec t eg ec 0
Sample Output
arlo/hot dourm/stop flub/school pleve/bus zym/seat iv/eg otas/ec re/t
刚开始隐隐约约觉得要构图,但是在图这方面我的知识比较匮乏,只好试试硬着头皮DFS,也考虑到了剪枝,但由于没有构图,深搜的深度是n,TLE了。
参考了网上的题解,构图判断两图是否同构。
#include <algorithm>
#include <iostream>
#include <string>
#include <stdio.h>
#include <queue>
#include <string.h>
#include <vector>
#include <iomanip>
#include <map>
#include <stack>
#include <functional>
#include <list>
#include <cmath>
using namespace std;
#define MAX_N 30 // 最大点数
struct Node { // 点
string s; // 点中信息
int match; // 匹配点在另一张图中的编号
int inDegree; // 入度
int outDegree; // 出度
Node() {}
Node(string sIn, int m = -1, int i = 0, int o = 0) {
s = sIn;
match = m;
inDegree = i;
outDegree = o;
}
};
Node N1[MAX_N], N2[MAX_N]; // 图一图二的点
bool G1[MAX_N][MAX_N], G2[MAX_N][MAX_N]; // 图一图二
int n, n1, n2; // n为题意n,n1为图一点数,n2为图二点数
map<string, int> M1, M2; // 图一图二字符串和下标的对应关系
bool succeed; // 是否搜到了答案
void makeG() {
M1.clear();
M2.clear();
n1 = n2 = 0;
memset(G1, false, sizeof(G1));
memset(G2, false, sizeof(G2));
for (int i = 0; i < n; i++) { // 建图一
string s1, s2;
cin >> s1 >> s2;
if (M1.find(s1) == M1.end()) {
M1[s1] = n1;
N1[n1] = Node(s1, -1, 0, 1);
n1++;
} else {
N1[M1[s1]].outDegree++;
}
if (M1.find(s2) == M1.end()) {
M1[s2] = n1;
N1[n1] = Node(s2, -1, 1, 0);
n1++;
} else {
N1[M1[s2]].inDegree++;
}
G1[M1[s1]][M1[s2]] = true;
}
for (int i = 0; i < n; i++) { // 建图二
string s1, s2;
cin >> s1 >> s2;
if (M2.find(s1) == M2.end()) {
M2[s1] = n2;
N2[n2] = Node(s1, -1, 0, 1);
n2++;
} else {
N2[M2[s1]].outDegree++;
}
if (M2.find(s2) == M2.end()) {
M2[s2] = n2;
N2[n2] = Node(s2, -1, 1, 0);
n2++;
} else {
N2[M2[s2]].inDegree++;
}
G2[M2[s1]][M2[s2]] = true;
}
}
void cut() { // 深搜前剪枝
for (int j, i = 0, k; i < n1; i++) {
int sameDegreeNum = 0;
for (j = 0; j < n2; j++) {
if (N1[i].inDegree == N2[j].inDegree && N1[i].outDegree == N2[j].outDegree) {
k = j;
sameDegreeNum++;
}
}
if (sameDegreeNum == 1) { // 如果图一图二中有且仅有两点i、j且i与j的出度入度相同,那么ij必然为对应点
N1[i].match = k;
N2[k].match = i;
}
}
}
void DFS(int pos) {
if (pos == n1) {
succeed = true;
return;
}
if (N1[pos].match != -1) { // 如果这个点已经匹配完成(cut函数剪枝)
DFS(pos + 1);
return;
}
for (int i = 0; i < n2; i++) {
if (N2[i].match == -1 && N1[pos].inDegree == N2[i].inDegree && N1[pos].outDegree == N2[i].outDegree) {
int j, k;
for (j = 0; j < n1; j++) { // 如果点pos和点i是可以匹配的,但是在图一中有一个点j,pos连接到j,且j有在图二中的对应点,但是点i并不连接到j的对应点,那么这是不同构的
if (j != pos && G1[pos][j] && N1[j].match != -1 && !G2[i][N1[j].match]) break;
}
for (k = 0; k < n1; k++) { // 如果点pos和点i是可以匹配的,但是在图一中有一个点j,j连接到pos,且j有在图二中的对应点,但是j的对应点并不连接到点i,那么这是不同构的
if (k != pos && G1[k][pos] && N1[k].match != -1 && !G2[N1[k].match][i]) break;
}
if (j == n1 && k == n1) { // 以上两种不同构的情况都没有出现,继续
N1[pos].match = i;
N2[i].match = pos;
DFS(pos + 1);
if (succeed) return;
N1[pos].match = N2[i].match = -1;
}
}
}
}
int main() {
std::ios::sync_with_stdio(false);
bool firstTime = true;
while (1) {
cin >> n;
if (n == 0) break;
if (!firstTime) cout << endl;
firstTime = false;
makeG();
cut();
succeed = false;
DFS(0);
for (map<string, int>::iterator iter = M1.begin(); iter != M1.end(); iter++) {
cout << iter->first << "/" << N2[N1[iter->second].match].s << endl;
}
}
//getchar();
//getchar();
return 0;
}
本文介绍了一种解决翻译文件中双词短语自动重构的问题,通过构建和匹配两个排序列表来实现从样本短语及其翻译中重建原始翻译的过程。详细解释了输入格式、输出要求以及算法实现,包括使用深度优先搜索(DFS)进行匹配,并通过剪枝优化减少计算复杂度。

562

被折叠的 条评论
为什么被折叠?



