http://pat.zju.edu.cn/contests/pat-a-practise/1032
浙大2012年上机复试题B
1032. Sharing (25)
To store English words, one method is to use linked lists and store a word letter by letter. To save some space, we may let the words share the same sublist if they share the same suffix. For example, "loading" and "being" are stored as showed in Figure 1.

Figure 1
You are supposed to find the starting position of the common suffix (e.g. the position of "i" in Figure 1).
Input Specification:
Each input file contains one test case. For each case, the first line contains two addresses of nodes and a positive N (<= 105), where the two addresses are the addresses of the first nodes of the two words, and N is the total number of nodes. The address of a node is a 5-digit positive integer, and NULL is represented by -1.
Then N lines follow, each describes a node in the format:
Address Data Next
where Address is the position of the node, Data is the letter contained by this node which is an English letter chosen from {a-z, A-Z}, andNext is the position of the next node.
Output Specification:
For each case, simply output the 5-digit starting position of the common suffix. If the two words have no common suffix, output "-1" instead.
Sample Input 1:11111 22222 9 67890 i 00002 00010 a 12345 00003 g -1 12345 D 67890 00002 n 00003 22222 B 23456 11111 L 00001 23456 e 67890 00001 o 00010Sample Output 1:
67890Sample Input 2:
00001 00002 4 00001 a 10001 10001 s -1 00002 a 10002 10002 t -1Sample Output 2:
-1
考察链表以及相同子链表的搜索记录,一开始想用STL的map来做,发现很麻烦而且结果不对。参考天勤论坛的题解,发现自己思路错了。
解题思路:用一个数组来存储所有链表结点的空间,数组下标为结点地址;先遍历第一个链表并标记,当遍历第二个链表时如果遇到第一个链表的标记,说明两个链表在标记处汇合,当前标记的地址即是它们首次汇合的地址。注意不需要用到结点保存的字符Data。
#include <cstdio>
/**
* 定义存储元素的结构体
* flag是用来标记该元素是不是第一个列表中的结点
* next为下一个节点地址
*/
struct NodeType
{
int flag, next;
};
int main(int argc, char *argv[])
{
NodeType nodes[110000] = {0}; // 定义存储所有结点的数组, 数组下标表示地址
int a1, a2, a, next; // 分别定义存储第一、第二列表首地址、
// 结点地址和后一个结点地址的变量
int num; // 定义存储结点总数的变量
int i; // 迭代变量
scanf("%d%d%d", &a1, &a2, &num); // 输入信息
while (num--)
{
scanf("%d%*s%d", &a, &next); // 内容字符不起作用,空读(%*s)
nodes[a].next = next;
}
// 遍历第一个列表的所有结点,如果某个结点同时也是第一个列表的结点,说明它们
// 开始公用结点了
i = a1;
while (i != -1)
{
nodes[i].flag = true;
i = nodes[i].next;
}
// 遍历第二个列表的结点
i = a2;
while(i != -1 && !nodes[i].flag)
{
i = nodes[i].next;
}
// 输出结果
if (i == -1)
puts("-1");
else
printf("%05d\n", i);
return 0;
}