首页 > 试题广场 >

Sharing (25)

[编程题]Sharing (25)
  • 热度指数:2303 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 64M,其他语言128M
  • 算法知识视频讲解
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).

输入描述:
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}, 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.
示例1

输入

11111 22222 9<br/>67890 i 00002<br/>00010 a 12345<br/>00003 g -1<br/>12345 D 67890<br/>00002 n 00003<br/>22222 B 23456<br/>11111 L 00001<br/>23456 e 67890<br/>00001 o 00010

输出

67890
#include <iostream>
using namespace std;
const int maxn=100010;
struct Node{
    int next,order;                    //本题跟数据域无关,以结点地址为唯一标识,可不设data
}node[maxn];
int main(){
    int head1,head2,n,adress;char c;
    cin>>head1>>head2>>n;
    for(int i=0;i<n;i++){    
        cin>>adress;
        cin>>c>>node[adress].next;
    }
    adress=head1;
    for(int i=1;adress!=-1;i++){      //对第一个链表标记顺序(结构体int型缺省为0),实际上是对第一个链表结点作标记
        node[adress].order=i;
        adress=node[adress].next;
    }
    adress=head2;
    int first=-1;
    while(adress!=-1){
        if(node[adress].order>0){     //类似hash,枚举第二个链表结点,若此结点在第一个链表中出现过,必为共用结点
            first=adress;
            break;                    //找到第一个共用结点就break
        }
        adress=node[adress].next;
    }
    if(first!=-1) printf("%05d",first);
    else printf("-1");
    return 0;
} 

编辑于 2019-01-07 15:54:56 回复(0)
令人匪夷所思的水题,我甚至都没用到字母
#include<iostream>
#include<cstring>

using namespace std;

#define MAX 100009

int pa, pb, N, nex[MAX], isa[MAX];

int main()
{
	cin >> pa >> pb >> N; int ad; char d;
	for (int i = 0; i < N; ++i) {
		cin >> ad; cin >> d >> nex[ad];
	}

	memset(isa, 0, sizeof(isa));
	while (pa != -1) { isa[pa] = 1; pa = nex[pa]; }
	while (pb != -1 && !isa[pb]) pb = nex[pb];
	
	if (pb == -1)cout << -1;
	else printf("%05d", pb);
	return 0;
}


发表于 2021-03-16 07:02:27 回复(0)
Sharing (25) 2018-12-20
 General mean: give you tow list, requst the first command node in both list.
 Result: Cost about 18 minues, A very funny and easy problem. To to that better
 you should skillfuly use set and map in STL. And it is very easy to come up
 with a solution.
 #include<iostream>
 #include<set>
 #include<map>
 using namespace std;
 map<int, int> adr;  // record the adress and next adress of a node;
 int start1, start2, n;
 set<int> set1;         //the adress of node in list1
 int main(){
 cin >> start1 >> start2 >> n;
 for (int i = 0; i < n; i++){
//I were expect that i can use interger-type to receive a char-type, but it turn to be worng... char t2; 
 int t1, t3;
 cin >> t1 >> t2 >> t3; 
 adr.insert(pair<int, int>(t1, t3));
 }
 while (start1 > 0 ){
 start1 = adr[start1];
 set1.insert(start1);
 }
 while (start2 > 0 ){
 start2 = adr[start2];
 if (set1.find(start2) != set1.end()){
 cout << start2 << endl;
 return 0;
 }
 }
 return 0;
 }

编辑于 2018-12-20 15:43:10 回复(0)
import java.util.*;
public class Main{
    public static void main(String[] args){
        HashMap<String,String> hashMap=new HashMap<String,String>();
        Scanner sc=new Scanner(System.in);
        String start1=sc.next();
        String start2=sc.next();
        int n=sc.nextInt();
        for(int i=0;i<n;i++){
            String start=sc.next();
            String value=sc.next();
            String end=sc.next();
            hashMap.put(start,end);
        }
        LinkedList<String> list1=new LinkedList<String>();
        LinkedList<String> list2=new LinkedList<String>();
        list1.add(start1);
        String addr1=hashMap.get(start1);
        while(addr1!=null){
            list1.add(addr1);
            addr1=hashMap.get(addr1);
        }
        list2.add(start2);
        String addr2=hashMap.get(start2);
        while(addr2!=null){
            list2.add(addr2);
            addr2=hashMap.get(addr2);
        }
        int index1=list1.size()-1;
        int index2=list2.size()-1;
        while(list1.get(index1).equals(list2.get(index2))){
            index1--;
            index2--;
        }
        if(index1==list1.size()-1){
            System.out.println("-1");
        }else{
            System.out.println(list1.get(++index1));
        }
    }
}

发表于 2018-10-05 16:07:04 回复(0)
啥头像
总体思路:
        就是找两个链表的第一个公共节点。
        长的先走差值,再同时走,知道第一个相等值

代码如下:
#include <iostream>
#include <stdio.h>

using namespace std;

int data[100000];

int main()
{
    // 读入数据
    int addr1, addr2, N, addr, next; char val;
    scanf("%d %d %d", &addr1, &addr2, &N);
    for(int i=0; i<N; i++) {
        scanf("%d %c %d", &addr, &val, &next);
        data[addr] = next;
    }

    // 找出两个链表的第一个节点
    int len1=0, len2=0; addr = addr1;
    while(addr != -1) {
        len1++; addr = data[addr];
    }
    addr = addr2;
    while(addr != -1) {
        len2++; addr = data[addr];
    }
    if(len1 > len2) {
        int len = len1 - len2;
        while(len--) {
            addr1 = data[addr1];
        }
    } else {
        int len = len2 - len1;
        while(len--) {
            addr2 = data[addr2];
        }
    }
    while(addr1>=0 && addr2>=0 &&addr1 != addr2) {
        addr1 = data[addr1];
        addr2 = data[addr2];
    }
    if(addr1>=0) {
        printf("%05d", addr1);
    } else {
        printf("-1");
    }
    return 0;
} 


发表于 2015-12-19 23:58:54 回复(1)
此题在处理的时候将数据存储为 data[address]=next 会方便很多。
从第一个word的头结点出发,然后做一次遍历,并进行标记。
然后从第二个word的头结点出发,进行遍历,遇到已标记的则退出。
即为所求。
发表于 2015-06-21 23:46:33 回复(0)
只要 判断 哪个 next 出现两次就好了。别的什么都不用管。
发表于 2015-12-16 22:22:27 回复(2)
//hash映射
#include<iostream>
#include<unordered_map>
using namespace std;

unordered_map<string,char>e;
unordered_map<string,string>ne;

void insert(string&s,char k,string&t){
    e[s]=k;
    ne[s]=t;
}

int main(){
    string begin1,begin2,begin3;
    string a="";
    string b="";
    cin>>begin1>>begin2;
    begin3=begin1;
    int idx=0;
    int n;
    cin>>n;
    string s1,t1;
    char elem;
    while(n--){
        cin>>s1>>elem>>t1;
        insert(s1,elem,t1);
    }
    while(begin1!="-1"){
        a+=e[begin1];
        begin1=ne[begin1];
    }
    //cout<<a<<endl;
    while(begin2!="-1"){
        b+=e[begin2];
        begin2=ne[begin2];
    }
    //cout<<b<<endl;
    char temp;
    for(int i=a.size()-1,j=b.size()-1;i>=0&&j>=0;i--,j--){
        if(a[i]==b[j]){
            temp=a[i];
            idx++;
        }
        else break;
    }
    if(idx==0){
        cout<<-1;
        return 0;
    }
    idx=a.size()-idx;
    while(idx--){
        begin3=ne[begin3];
    }
    cout<<begin3;
    
    return 0;
}

发表于 2020-12-28 14:17:38 回复(0)
C++的map是一个好东西🤣
#include<iostream>
#include<string>
#include<map>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<bits/stdc++.h>

#define INF 2147483647
#define MIN INF+1
#define ll long long

using namespace std;

struct node {
    string address;
    char data;
    string next;
};

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);

    string add1, add2;
    int N;
    cin >> add1 >> add2;
    cin >> N;

    node n[N];
    map<string, int> m;     // from address to node itself

    for(int i = 0; i < N; i++) {
        cin >> n[i].address >> n[i].data >> n[i].next;
        m[n[i].address] = i;
    }

    string word1_begin = add1;
    map<string, int> add_map;
    while(word1_begin != "-1") {
        add_map[word1_begin] = 666;
        word1_begin = n[m[word1_begin]].next;
    }

    string word2_begin = add2;
    while(word2_begin != "-1") {
        if(add_map[word2_begin] == 666) {
            cout << word2_begin << endl;
            return 0;
        }
        if(m.find(n[m[word2_begin]].next) == m.end()) {
            break;
        }
        word2_begin = n[m[word2_begin]].next;
    }
    cout << -1 << endl;
    return 0;
}


发表于 2020-09-19 23:27:14 回复(0)
牛客网的测试点比PAT宽松,这个代码在牛客网全通过,在PAT要错两个,不过稍加改动也能通过
思路就是如果作为共同的suffix,其地址必然在next域出现两次,所以整个计数的cnt,只要不等于-1,每出现一次地址就++,然后遍历寻找cnt == 2的点就可以了,没有这个点就输出-1
PAT之所以错,是因为PAT会提供一些没有在单词字母链中出现过的无关结点,这些结点会干扰结果
#include <cstdio>

int main(){
    int a1,a2,n,diu1,temp;
    char diu2;
    scanf("%d %d %d",&a1,&a2,&n);
    int next[100001] = {0};
    for(int i = 0;i < n;i++){
        scanf("%d %c %d",&diu1,&diu2,&temp);
        if(temp != -1)
            next[temp]++;
    }
    for(int i = 0;i < 100001;i++){
        if(next[i] == 2){
            printf("%05d",i);
            return 0;
            }
        }
    printf("-1");
}


发表于 2020-06-23 22:19:01 回复(1)
在pta里测试点4过不了,有没有大佬指点一下
#include <iostream>
#include <climits>
#include <cmath>
#include <cctype>
#include <algorithm>
#include <string>
#include <string.h>
#include <vector>
using namespace std;

bool cmp1(int a, int b) {
	return a > b;
}
int main() {
	int a, b, n, np[100000], i;
	scanf("%d %d %d", &a, &b, &n);
	for (i = 0; i < n; i++) {
		int p, c;
		scanf("%d %c %d", &p, &c, &np[i]);
	}
	sort(np, np+i, cmp1);
	for (i = 0; i < n; i++) {
		if (np[i] == np[i-1] && np[i-1] != -1) {
			printf("%05d\n", np[i-1]);
			return 0;
		}
	}
	printf("-1\n");
  	return 0;
}


发表于 2020-05-31 10:31:13 回复(0)

#include<iostream>
(720)#include<vector>
#include<map>
using namespace std;
struct node {
	char val;
	int next;
	node() :val(0), next(-1) {}
	node(char v, int n) :val(v), next(n) {}
};
node nodes[100000];
int main() {
	int head1, head2, n;
	cin >> head1 >> head2 >> n;
	map<int, int>mymap;
	for (int i = 0; i < n; i++) {
		int cur, next;
		char val;
		cin >> cur >> val >> next;
		nodes[cur] = node(val, next);
	}
	int end1 = head1, end2 = head2;
	int result = -1;
	while (end1 != -1 ) {
		mymap[end1]++;
		end1 = nodes[end1].next;
	}
	while (end2 != -1) {
		mymap[end2]++;
		end2 = nodes[end2].next;
	}
	end1 = head1;
	while (end1 != -1) {
		if (mymap[end1] == 2) {
			result = end1;
			break;
		}
		end1 = nodes[end1].next;
	}
    if(result!=-1){
      printf("%05d", result);
    }
    else{
        printf("-1");
    }

}


编辑于 2020-04-16 22:10:22 回复(0)
这题pta上用python最后一个用例连数都获取不完就超时了,绝望
a = input().split()
d = {}
for i in range(int(a[2])):
    b = input().split()
    d[b[0]] = b[2]

b = [[a[0]],[a[1]]]
for i in range(2):
    while a[i] != '-1':
        b[i].append(d[a[i]])
        a[i] = d[a[i]]

for i in range(-1,-min((len(b[0]),len(b[1]))) - 1,-1):
    if b[0][i] != b[1][i]:
        print(b[0][i + 1])
        break
else:
    print(b[0][i])

编辑于 2020-02-22 16:35:30 回复(0)
#include<iostream>
#include<map>
using namespace std;
int main(void){     map<int, vector<int> > pre;     int ad1, ad2, n;     char c;     cin >> ad1 >> ad2 >> n;     for (int i = 0; i < n; i++){         cin >> ad1 >> c >> ad2;         pre[ad2].push_back(i);         if (pre[ad2].size() == 2 && ad2 != -1){             printf("%05d", ad2);             return 0;         }     }     cout << "-1";     return 0;
} 
编辑于 2019-07-23 19:17:07 回复(0)
ha,hb,n=raw_input().split()
Link={}
for _ in range(int(n)):
    address,data,Next=raw_input().split()
    Link[address]=Next
pa,pb=ha,hb
while pa!=pb:
    pa=hb if pa=='-1' else Link[pa]
    pb=ha if pb=='-1' else Link[pb]
print pa
不用建立链表,因为字符串就代表了地址,搞个map就行,字母其实也用不上,维持两个指针,分别指向两个链表a,b,因为len(a)+len(b)=len(b)+len(a),所以在两次循环之后必然会由于以下两种情况跳出循环:指针相遇或者都到链表尾了
发表于 2019-01-17 19:31:05 回复(0)


import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        while(sc.hasNext()) {
            String s1 = sc.next();
            String s2 = sc.next();
            String tempS1 = s1;
            String tempS2 = s2;
            int n = sc.nextInt();
            Map<String,String> map = new HashMap<>();

            for (int i = 0;i<n;i++){
                String a = sc.next();
                String b = sc.next();
                String c = sc.next();
                map.put(a,c);

            }
            int len1 = 1;
            int len2 = 1;
            while (!tempS1.equals("-1")){
                tempS1 = map.get(tempS1);
                len1++;
            }
            while (!tempS2.equals("-1")){
                tempS2 = map.get(tempS2);
                len2++;
            }
            if (len1>len2){
                int t = len1-len2;
                while (t>0){
                    s1 = map.get(s1);
                    t--;
                }
            }
            if (len2>len1){
                int t = len2-len1;
                while (t>0){
                    s2 = map.get(s2);
                    t--;
                }
            }
            while (!s1.equals(s2)){
                s1 = map.get(s1);
                s2 = map.get(s2);
            }
            System.out.println(s1);
        }
    }
}
发表于 2018-11-23 19:50:35 回复(0)
w1,w2,n=input().split()
D,S={},set([])
for i in range(int(n)):
    a,b,c=input().split()
    D[a]=c
while w1!='-1':
    S.add(w1)
    w1=D[w1]
while w2!='-1':
    if w2 in S:
        print(w2)
        break
    w2=D[w2]
else:
    print(-1)
还是用in-build数据结构比较轻松
发表于 2018-09-04 18:04:39 回复(0)
思路:建立两个vector数组记录链的下标,然后从后面往前看第一个不同的地址然后就输出前一个
相同的。
#include <iostream>
#include <list>
#include <fstream>
#include <iomanip>
#include <vector>
// 求公共后缀的开始

using namespace std;

struct ilist
{
    int adr;
    char data;
    int nAdr;
};

#ifndef debug
ifstream ifile("case.txt");
#define cin ifile
#endif

int main()
{
    int sta1, sta2, n;
    cin >> sta1 >> sta2 >> n;
    vector<int> mlist1;
    vector<int> mlist2;
    int mark[100000][2];// 0 存储data 1 存储nAdr
    int tmp;
    char cTmp;
    for (int i = 0; i < n; i++)
    {
        cin >> tmp;
        cin >> cTmp >> mark[tmp][1];
        mark[tmp][0] = cTmp;
    }
    int index;
    for (index = sta1; mark[index][1] != -1;)
    {
        mlist1.push_back(index);
        index = mark[index][1];
    }
    mlist1.push_back(index);// 存储-1的节点
    for (index = sta2; mark[index][1] != -1;)
    {
        mlist2.push_back(index);
        index = mark[index][1];
    }
    mlist2.push_back(index);// 存储-1的节点
    // 开始比较
    int sameAdr = -1;
    for (int i = mlist1.size() - 1, j = mlist2.size() - 1; i >= 0 && j >= 0; i--, j--)
    {
        if (mlist1[i] != mlist2[j])
        {
            break;
        }
        else
        {
            sameAdr = mlist1[i];
        }
    }
    if (sameAdr != -1)
        cout << setfill('0') << setw(5) << sameAdr << endl;
    else
        cout << sameAdr << endl;
    system("pasue");
}

发表于 2018-08-29 10:45:57 回复(0)
#include<iostream>
#include<map>
#include<string>
using namespace std;

class Node
{
public:
    string data;
    int next;
};

int main()
{
    int head1, head2, N;
    cin >> head1 >> head2 >> N;
    map<int, Node> seq;
    
    for(int i = 0; i < N; i++)
    {
        int add, next;
        string data;
        cin >> add >> data >> next;
        Node node;
        node.data = data;
        node.next = next;
        seq[add] = node;
    }

    //处理
    int p1 = head1, p2 = head2;
    if(p1 == -1 || p2 == -1)
        cout << -1;
    else
    {
        map<int, int> parent1, parent2;
        parent1[head1] = -1;
        parent2[head2] = -1;
        while(seq[p1].next != -1)
        {
            parent1[seq[p1].next] = p1;
            p1 = seq[p1].next;
        }
        while(seq[p2].next != -1)
        {
            parent2[seq[p2].next] = p2;
            p2 = seq[p2].next;
        }
        if(seq[p1].data != seq[p2].data)
            cout << -1;
        else
        {
            while(parent1[p1] != -1 && parent2[p2] != -1 && seq[p1].data == seq[p2].data)
            {
                p1 = parent1[p1];
                p2 = parent2[p2];
            }
            if(seq[p1].data == seq[p2].data)
                printf("%05d", p1);
            else
                printf("%05d", seq[p1].next);
        }

    }
    

    system("pause");
    return 0;
}
发表于 2018-03-09 20:55:16 回复(0)
全部入栈,逐个出栈判断。
#include "iostream"
#include "vector"
#include "string"
#include "cstring"
#include "queue"
#include "stack"
#include "map"
#include "ctime"
#include <limits.h>
#include <algorithm>
using namespace std;

struct Data
{
	int index;
	int next;
	char ch;
};

vector<Data> Input(100001);
int main()
{
	int startAdd, finalAdd;
	int N;
	cin >> startAdd >> finalAdd >> N;
	vector<int> end;
	for (int i = 0; i < N; i++)
	{
		int s, f;
		char k;
		cin >> s >> k >> f;
		Input[s].index = s;
		Input[s].ch = k;
		Input[s].next = f;
		if (f == -1)
			end.push_back(s);
	}
	int count = 0, pos = 0;
	stack<Data> s1, s2;
	while (startAdd != -1)
	{
		s1.push(Input[startAdd]);
		startAdd = Input[startAdd].next;
	}
	while (finalAdd != -1)
	{
		s2.push(Input[finalAdd]);
		finalAdd = Input[finalAdd].next;
	}
	while (s1.size() != 0 && s2.size() != 0)
	{
		if (s1.top().ch == s2.top().ch)
		{
			pos = s1.top().index;
			s1.pop(), s2.pop();
			
			count++;
		}
		else
			break;
	}
	if (count == 0)
		cout << -1;
	else
		printf("%5d", pos);
}

发表于 2017-03-27 22:26:57 回复(0)