目录
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.
For each case, the first line contains two addresses of nodes and a positive N (<= 10^5), 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}, and Next is the position of the next node.
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.
输入:
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 00010 00001 00002 4 00001 a 10001 10001 s -1 00002 a 10002 10002 t -1输出:
67890 -1
AC代码~
#include<stdio.h>
#include<stdlib.h>
typedef struct Linklist {
char ch;
struct Linklist* next;
int add;
int nextadd;
} L;
int Linklen(L* h) { // 求链表长度
L* tmp = h->next;
int len = 0;
while (tmp != NULL) {
len++;
tmp = tmp->next;
}
return len;
}
int main() {
int n, f1, f2;
while (scanf("%d%d%d", &f1, &f2, &n) != EOF) {
L* a = (L*)malloc(n * sizeof(L)); // 结构体数组
L* h1 = (L*)malloc(sizeof(L)); // 头节点
L* h2 = (L*)malloc(sizeof(L));
for (int i = 0; i < n; i++)
scanf("%d %c %d", &a[i].add, &a[i].ch, &a[i].nextadd);
int head1, head2;
for (int i = 0; i < n; i++) { // 找出第一个节点的编号
if (a[i].add == f1)
head1 = i;
if (a[i].add == f2)
head2 = i;
}
h1->next = NULL;
h2->next = NULL;
h1->next = &a[head1];
h2->next = &a[head2];
L* tail1 = h1->next; // 尾指针
L* tail2 = h2->next;
while (tail1->nextadd != -1) { // h1链连接好
int i = 0;
for (i = 0; i < n; i++) {
if (a[i].add == tail1->nextadd) {
tail1->next = &a[i];
tail1 = &a[i];
break;
}
}
}
tail1->next = NULL;
while (tail2->nextadd != -1) { // h2链连接好
int i = 0;
for (i = 0; i < n; i++) {
if (a[i].add == tail2->nextadd) {
tail2->next = &a[i];
tail2 = &a[i];
break;
}
}
}
tail2->next = NULL;
int len1 = Linklen(h1);
int len2 = Linklen(h2);
int dist;
L* longL; // long指向较长的链表
L* shortL; // short指向较短的链表
if (len1 >= len2) { // dist为二者长度差值
longL = h1->next;
shortL = h2->next;
dist = len1 - len2;
} else {
longL = h2->next;
shortL = h1->next;
dist = len2 - len1;
}
while (dist > 0) { // 较长的先走dist步 目的是使二者对齐
dist--;
longL = longL->next;
}
longL = longL->next; // 二者都走一步(第一个节点就相等不算“公共后缀”)
shortL = shortL->next;
while (longL != NULL) { // 相等的节点则是公共后缀的第一个
if (longL->ch == shortL->ch && longL->nextadd == shortL->nextadd) {
printf("%d\n", longL->add);
break;
}
longL = longL->next;
shortL = shortL->next;
}
if (longL == NULL)
printf("-1\n");
}
return 0;
}