【CQTSC2016】路由表 题解

题目大意

  有 n 个操作,分Add和Ask两种。
  Add操作就是添加一个字符串(把 IPv4 地址转成 32 位的二进制串,取前L位,L为掩码),保证每次Add都不相同。
  Ask操作给出询问串S(同样是IPv4地址转成32位二进制串)和区间[L, R],对于这次Ask之前的Add操作,从头开始,每Add一次,S就会找已经Add的串中最长的并且是S前缀的串作为匹配。询问第L个Add操作到第R个Add操作中,S的匹配更新了多少次。

【30%】n<=1000

  n太小了,对于每个询问,直接暴力枚举前R个Add操作中,S的匹配更新了多少次,然后这么多次更新中,有多少次是在L以后的。

  时间复杂度O(n^2)

【100%】n<=10^6

  不能枚举操作了。但是注意到S的匹配必须是S的前缀,因此我们考虑构一棵trie。

  注意这棵trie有个很鲜明的特征:由于每次Add都不相同,所以trie上的每个节点最多代表一个字符串。

  因此S在trie上走的时候,最多遇到32个字符串,也就是说,S的匹配最多只有32个,这就是该算法比上一个算法优的关键因素。

  有了这个trie,我们可以轻松把32个匹配全部取出来,然后按时间戳排个序,看看哪次会更新,然后这么多次更新中,有多少次是在L以后、R以前的。

  时间复杂度 $O(32 \cdot n)$