题目

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 (≤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

whereAddress 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.

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 00010

Sample Output 1:

67890

Sample Input 2:

00001 00002 4

00001 a 10001

10001 s -1

00002 a 10002

10002 t -1

Sample Output 2:

-1

题目大意

给出两个单词,每个单词都是以链表的形式存储,链表每个节点存储一个字符,然后指向下一个节点,最后一个节点指向NULL(以-1代替)

输入 给出了每个节点的地址、内容、指向下一个节点的地址

要求找到两个单词的共同后缀的第一个字符的地址(比如loading和being就应该输出字符i的地址),如果不存在公共后缀,输出 -1。

思路分析

1. 自以为是的错误思路(自闭的一下午的开始,如果不感兴趣可以直接看下面正确思路)

刚开始我是这样想的: 既然是两个单词的公共部分,所以要找的那个地址一定是在所有给定的<Address Data NextAddress>格式数据中,在 NextAddress位置出现了两次的,而且是唯一出现了两次的,因为后面再一样的也不会再给出。

(如果两个单词的某个节点的nextAddress都指向了同一个地址,那么后续肯定就一样了,比如loadingd指向了ibeinge指向了i,所以i就是他们共同后缀的开始,这也就是为什么我统计的是<Address Data NextAddress>NextAddress出现的次数)

比如题目中 loadingbeing 的 样例第一组,可以看到只有 i 对应的 67890 地址出现了两次。

所以,直接开一个大于 100000 的一维数组 count[],用节点地址做下标。 每次得到一个 <Address Data Next> 数据,令 count[NextAddres]++; 最后遍历一遍,若 count[i] == 2i 即为所求。

因为这个思路记录的是每次的 NextAddress,所以如果第一个字母就是一样的(比如abcdhagjkl),那么就没有类似count[beginAddress]++操作。所以代码中补充一下,如果题目给定的两个起始地址相同,则直接输出这个起始地址。

怎么样,看到现在是不是觉得我分析的很有道理,而且代码写起来也很简单

#include <iostream>
using namespace std; // 这种写法 对于 loading ing 会输出 -1,正确应该输出 i 的地址
int main() {
int s1, s2, n;
cin >> s1 >> s2 >> n;
int count[100000] = {0};
// 针对第一个地址就相同的情况
if (s1 == s2) {
printf("%05d", s1);
return 0;
}
int id; char data; int nextid;
for (int i = 0; i < n; ++i) {
cin >> id >> data >> nextid;
if (nextid == -1) continue;
// id data next统计了出现了两次的next
count[nextid]++;
}
// 写法二
// 找到第一个出现次数大于1的地址(因为只有一个地址会出现2次),直接输出并返回
for (int i = 0; i < 100000 ;++i) {
if (count[i] > 1) {
printf("%05d", i);
return 0;
}
}
// 没找到就输出 -1
printf("-1");
// 写法二
// 找到了也不急着输出,全部遍历完了输出
// int ans = -1;
// for (int i = 0; i < 100000 ;++i) {
// if (count[i] > 1) {
// ans = i;
// }
// }
// ans == -1 ? printf("-1") : printf("%05d", ans);
return 0;
}

你可以看到我的代码下半部分是有两种写法的,总结来说就是

第一中写法,找到的是count数组中第一个出现了2次的地址,直接输出。

第二种写法,找到的是count数组中最后一个出现了2次的地址,遍历完了再输出。

我自己采用的是第一种写法,然后提交之后就是测试2和4答案错误,百思不得其解,各种搜索,搜出来的都是结构体数组+标志位+两次遍历,这个一会再说,既然没办法解决问题,那我就放弃这个思路吧,偏偏这个时候让我看到一个人的评论,他的思路和我竟然一样,点进去看他的那篇博客,我开心了好久,因为他的代码竟然AC了,但我的没有,为什么,就是因为他采用的是我上面提到的第二种写法(也就是代码中注释了的那部分)。

于是我就开始自闭了,按照分析,这个count数组中应该只有一个位置是2,这个地址应该是唯一的才对,所以不管是第一种写法(找到出现两次的地址就输出)还是第二中写法(全部遍历一次,最后得到的是最后一个出现两次的地址)应该是相同结果,但事实就是第二种写法AC,第一种写法答案错误。我不知道这个测试用例是什么样的,所以没办法确定这两种写法是否针对某个特殊用例具有不同结果。

但好在我的一个同学给出我举出一个例子,推翻了这个思路(不管方式一还是方式二都是错的)。比如 beinging,答案应该是输出 i 的地址,

测试用例可以是
11111 22222 5
11111 b 12345
12345 e 22222
22222 i 00003
00003 n 00004
00004 g -1

但是按我这种思路,对于i的地址22222count[22222]根本不会得到2,因为22222一次出现在address的位置,一次出现在nextAddress的位置,而我count统计的是nextAddress位置,所以,这种思路只能输出 -1

这就是我自闭的一下午,至于那个人的写法为什么会AC,反正我不明白,可能因为测试用例中没有出现我举出的这种例子吧。

2. 普遍的正确思路

也就是所谓的 结构体数组+标志位+两次遍历,用结构体保存每个节点,节点字段包括 内容(字符),下一个节点的地址,标志位(是否已访问),用一个数组存储全部节点,节点的地址作为数组下标。

首先从第一个单词的开始节点(地址)出发,顺着链表逐个访问节点,并将遍历到的节点的标志位置为;再从第二个单词的开始节点(地址)出发,顺着链表逐个访问节点,如果途中遇到某个节点的标志位已经置位,说明从这个节点往后都是它两的公共部分,如果链表全部节点都没有置位,说明这两个单词没有公共后缀输出-1。

#include <iostream>
using namespace std; struct Node {
char data; // 值
int nextid; // 下个节点
bool visit; // 是否访问过
}node[100000]; int main() {
int s1, s2, n;
cin >> s1 >> s2 >> n; int id; char data; int nextid;
for (int i = 0; i < n; ++i) {
cin >> id >> data >> nextid;
// 创建新节点
node[id] = {data, nextid, false};
}
// 按照第一个单词,节点都访问一遍,比较为true
for (int i = s1; i != -1; i = node[i].nextid) {
node[i].visit = true;
}
// 按照第二个单词,再遍历,若碰到一个visit为true的节点说明后面和第一个单词一样了
// 当前节点就是公共后缀的第一个节点
for (int i = s2; i != -1; i = node[i].nextid) {
if(node[i].visit == true) {
printf("%05d", i);
return 0;
}
}
// 否则就有没有公共后缀
printf("-1");
return 0;
}

PAT 1032 Sharing (25分) 从自信到自闭的更多相关文章

  1. PAT 甲级 1032 Sharing (25 分)(结构体模拟链表,结构体的赋值是深拷贝)

    1032 Sharing (25 分)   To store English words, one method is to use linked lists and store a word let ...

  2. 1032 Sharing (25分)

    1032 Sharing (25分) 题目 思路 定义map存储所有的<地址1,地址2> 第一set存放单词1的所有地址(通过查找map) 通过单词二的首地址,结合map,然后在set中查 ...

  3. 【PAT甲级】1032 Sharing (25 分)

    题意: 输入两个单词的起始地址和一个正整数N(<=1e5),然后输入N行数据,每行包括一个五位数的字母地址,字母和下一个字母的地址.输出这两个单词的公共后缀首字母的地址,若无公共后缀则输出-1. ...

  4. 1032 Sharing (25分)(数组链表)

    To store English words, one method is to use linked lists and store a word letter by letter. To save ...

  5. 【PAT】1032 Sharing (25)(25 分)

    1032 Sharing (25)(25 分) To store English words, one method is to use linked lists and store a word l ...

  6. PAT甲 1032. Sharing (25) 2016-09-09 23:13 27人阅读 评论(0) 收藏

    1032. Sharing (25) 时间限制 100 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue To store Engl ...

  7. PAT 1032 Sharing[hash][链表][一般上]

    1032 Sharing (25)(25 分) To store English words, one method is to use linked lists and store a word l ...

  8. PAT甲题题解-1032. Sharing (25)-链表水题

    #include <iostream> #include <cstdio> #include <algorithm> #include <string.h&g ...

  9. PAT (Advanced Level) 1032. Sharing (25)

    简单题,不过数据中好像存在有环的链表...... #include<iostream> #include<cstring> #include<cmath> #inc ...

随机推荐

  1. ACM思维题训练 Section A

    题目地址: 选题为入门的Codeforce div2/div1的C题和D题. 题解: A:CF思维联系–CodeForces -214C (拓扑排序+思维+贪心) B:CF–思维练习-- CodeFo ...

  2. 编译警告:warning: operation on ‘i’ may be undefined

    dest[i++]=src[i]; 这行代码,编译时会遇到警告: warning: operation on ‘i’ may be undefined(对于i变量的操作,有可能是未定义的) 改成 de ...

  3. 2019-2020Nowcoder Girl初赛 题解

    题目都不是很难,就是最后一题有点毒瘤 第一题:牛妹爱整除 这个你把一个进制数进行拆分,拆分成若干位,然后在取模,这样会发现如果是x进制的数,那么对x+1这个进制转化即满足条件. 举个例子:一个x进制数 ...

  4. F. Cards and Joy

    F. Cards and Joy 题目大意: 给你n个人,每一个人恰好选k张牌. 第一行是 n 和 k 第二行有n*k个数,代表有n*k张牌,每张牌上的数字 第三行有n个数,代表第i个人喜欢的数字 第 ...

  5. 使用 if elseif else 指定条件

    nrows = 4; ncols = 6; A = ones(nrows,ncols); 遍历矩阵并为每个元素指定一个新值.对主对角线赋值 2,对相邻对角线赋值 -1,对其他位置赋值 0. for c ...

  6. Linux的vi和vim编辑器

    Linux中分为:一般模式,插入模式和底行模式 一般模式(通过按iaoIAO键)-->插入模式 插入模式(按Esc键)--> 一般模式 一般模式(通过按:键)-->底行模式 底行模式 ...

  7. spring mvc 实现文件上传

    例:用户注册提交一个头像文件 第一步,创建项目 ,导入jar包 做文件上传除了要导入spring常规的jar包外,还要导入commons-fifileupload和commons-io这两个jar包. ...

  8. C# 判断文件格式的一些总结

    前提概述: 项目中 经常会有上传图片的地方  有的时候需要对图片类型做一些要求   这个时候就需要一些判断   虽然前段上传的时候可以去做类型的限制  或者后台接受的时候从file的type 中获取图 ...

  9. Zkeys:低门槛、易操作的智能云管理系统

    ZKEYS系统是一个功能强大的智能化管理系统,目前国内最大的IDC业务管理系统之一.功能模块涵盖用户中心系统.财务系统.工单系统.备案系统和云服务器.服务托管器.虚拟主机等产品的弹性在线购买及及时开通 ...

  10. SpringBoot基础实战系列(二)springboot解析json与HttpMessageConverter

    SpringBoot解析Json格式数据 @ResponseBody 注:该注解表示前端请求后端controller,后端响应请求返回 json 格式数据前端,实质就是将java对象序列化 1.创建C ...