[01trie]2021icpc第一场网络选拔赛G Longest Prefix Matching

The algorithm Longest Prefix Matching (LPM) Lookup is a method used by routers to find an exact matched routing entry in a routing table for the internet protocol (IP) domain. As we know, each entry in a routing table indicates a network or a network segment, so there may be several items that can match a given destination IP address at the same time. The method is called LPM because it matches the most definite or accurate entry with the longest mask bits.

For example, here is an IPv4 route table as below:

DestinationNextHop
192.168.20.16/281.1.1.1
192.168.0.0/162.2.2.2
0.0.0.0/03.3.3.3

If we want to find the next-hop IP address of the destination IP 192.168.20.19 in this table, there are two entries matched, 192.168.20.16/28 and 192.168.0.0/16. We can see that 192.168.20.19 matches the first 28 bits of 192.168.20.16 and the first 16 bits of 192.168.0.0 (i.e., (ip_dest & mask[0]) == ip[0] and (ip_dest & mask[1]) == ip[1]).

              192.     168.      20.      16
  ip[0]  11000000 10101000 00010100 00010000
mask[0]  11111111 11111111 11111111 11110000
         |---------> 28 bits <---------|

              192.     168.       0.       0
  ip[1]  11000000 10101000 00000000 00000000
mask[1]  11111111 11111111 00000000 00000000
         |--> 16 bits <--|

              192.     168.      20.      19
ip_dest  11000000 10101000 00010100 00010011

In other words, both network segments 192.168.20.16/28 and 192.168.0.0/16 can cover the destination IP address 192.168.20.19. In this situation, the routing entry 192.168.20.16/28 is selected, since it has the longest prefix mask matched (i.e., 28 > 16). So, the next-hop address of destination IP 192.168.20.19 is 1.1.1.1, but not 2.2.2.2.

In general, the routing table should contain a default route, which has the shortest possible prefix match, to fall back on in case that matches with all other entries failed. The default route in IPv4 is designated as the zero address, 0.0.0.0/0. The subnet mask effectively specifies all networks and is probably the shortest match. A routing lookup that does not match any other entries will fall back to this entry. In this case, the next-hop address will be 3.3.3.3.

For another example:

DestinationNextHop
10.1.0.0/24192.168.2.2
10.1.0.0/16192.168.3.3
0.0.0.0/0192.168.1.1

For IP messages with three destination addresses of 10.1.0.14 / 10.1.4.6 / 10.2.1.3 respectively, the matching results are as follows:

Destination IPMatching results
10.1.0.14Two network segment routing table entries match. According to the longest mask matching rule, the next-hop address is 192.168.2.2.
10.1.4.6It only matches the routing table entry of the second network segment, so the next-hop address 192.168.3.3 is returned.
10.2.1.3It does not match any table item, so it is thrown to the default route and returns the next-hop address 192.168.1.1.

Now, you are asked to read in the given routing entries and establish the routing table in memory, and then implement an LPM matching algorithm. The algorithm should look up the most accurate next-hop IP address of each given destination IP address according to the LPM matching rule. At the same time, performance is the key point of routing and forwarding. The faster the lookup algorithm, the better.

Input

The first line is the number of routing entries.

Starting from the second line, each line includes three columns, from left to right: destination network segment IP, the bit length of prefix mask, and next-hop IP address, separated by several spaces. For example:

Destination  Mask  NextHop
2.1.32.0     20    11.1.1.3
3.1.1.0      24    12.1.1.1

20 and 24 mean the bit length of the prefix mask of the corresponding network segment. It means that the first 20 bits (upper 20 bits) or the first 24 bits (upper 24 bits) of the destination IP address must be completely consistent with the destination address of the corresponding routing item.

After the description of routing entries, a new line indicates the number of destination IP addresses to be queried.

Each subsequent line gives a destination IP address to be queried. It is expected to return their next-hop IP address looked up from the routing table above.

The routing table has no more than 100,000 entries. And the number of queries is within 1,000,000.

Output

Each line of the output file corresponds to the query result of the destination IP address to be queried in each line of the input section.

Sample Input

10
10.13.11.0   27  30.30.120.80
10.14.0.0    16  30.31.110.78
68.24.0.0    18  88.41.120.73
68.24.5.0    24  88.41.114.78
68.24.11.0   28  88.41.120.80
29.40.4.0    24  49.57.113.78
29.40.10.0   23  49.57.120.73
29.40.11.1   32  49.57.120.78
240.0.0.0    4   4.4.4.12
0.0.0.0      0   1.1.1.1
3
68.24.5.109
29.40.10.133
192.168.1.2

结尾无空行

Sample Output

88.41.114.78
49.57.120.73
1.1.1.1

结尾无空行

Acknowledgment

ICT Products & Solutions of HUAWEI.

题意: 先给出n条数据,每条数据包括一个ip地址,需要匹配的长度len,以及应返回的ip地址。之后给出m次询问,每次询问给出一个ip地址,在已有的ip地址中寻找最长的能完成匹配的ip地址,这里的匹配指转换为32位二进制数后,前len位数字相等。

分析: 比较明显的01trie题,对于给出的n条数据可以把它们的前len位加入到trie中,并在结尾处节点打上标记cnt,cnt[i]记录以i节点结尾的01串对应的ip地址编号(答案串的编号),对于m次询问,把每个询问串转为01二进制后,query一遍得到最长的匹配位置即可。本题主要是处理读入数据比较麻烦,建议用scanf格式化读入。

具体代码如下:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <sstream>
using namespace std;

int n, m, son[3200000][2], cnt[3200000], idx;
char ans[100005][30];

void insert(int x, int len, int id)
{
	int now = 0;
	for(int i = 0; i <= 31; i++)
	{
		int t = (x>>(31-i))&1;
		if(!son[now][t])
			son[now][t] = ++idx;
		now = son[now][t];
		if(i == len-1)
		{
			cnt[now] = id;
			return;
		}
	}
}

int query(int x)
{
	int now = 0, t = 0;
	for(int i = 0; i <= 31; i++)
	{
		int tt = (x>>(31-i))&1;
		if(!son[now][tt])
			break;
		now = son[now][tt];
		if(cnt[now])
			t = cnt[now];
	}
	return t;
}

signed main()
{
	cin >> n;
	for(int i = 1; i <= n; i++)
	{
		int a, b, c, d, len;
		scanf("%d.%d.%d.%d%d%s", &a, &b, &c, &d, &len, ans[i]);
		if(len == 0)
			strcpy(ans[0], ans[i]);
		int binary;//把abcd转为二进制串binary 
		binary = (a<<24)|(b<<16)|(c<<8)|d;
		insert(binary, len, i);
	}
	cin >> m;
	for(int i = 1; i <= m; i++)
	{
		int a, b, c, d;
		scanf("%d.%d.%d.%d", &a, &b, &c, &d);
		int binary;//把abcd转为二进制串binary 
		binary = (a<<24)|(b<<16)|(c<<8)|d;
		printf("%s\n", ans[query(binary)]);
	}
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值