题目大意

给定 $n$($n\le 50000$) 个由小写英文字母构成的字符串,每个串的长度不超过 10,每个串有一个权值 $v$ ($1\le v\le 100000$)。

回答 $m$($m\le 50000$)组询问,询问格式为两个字符串 $p,s$,求输入中满足「以 $p$ 为前缀并且以 $s$ 为后缀」的串的最大权值。

解法

我的做法:字典树套字典树。

标程做法:将输入中长为 $k$ 的字符串变成 $k$ 个新字符串;

例子:

abc 变成

a#cba

ab#cba

abc#cba

用所有新串建一棵字典树。

对于查询 $p,s$ ,在字典树中查询 $p+`\#`+ \mathrm{reverse}(s)$ 。

实现要点

字典树的每个节点开长为 26 的数组(可能)会 MLE,可以用「左儿子-右兄弟」方式建树。

Highlights

我写了一个字典树模板类,自认为很 fancy。

#include <bits/stdc++.h>
using namespace std;
using ll = long long; template<class T>
struct trie{
struct node{
char x;
size_t l, r;
}; using val_t = T;
vector<pair<node,val_t>> a; val_t _null; trie(){
a.push_back({});
}
size_t size()const {
return a.size();
}
// LC-RS: left-child right-sibling
size_t get_child(size_t i, char x)const{
for(i=a[i].first.l; ; i=a[i].first.r){
if(a[i].first.x == x || !a[i].first.r)
return i;
}
} template <typename lambda>
void insert(const string &s, lambda &&upd){
size_t i=0;
upd(a[i].second);
for(auto x: s){
auto _i = get_child(i, x);
if(a[_i].first.x == x)
i = _i;
else{
if(!_i){
a[i].first.l=a.size();
}
else{
a[_i].first.r=a.size();
}
i = a.size();
a.push_back({});
a.back().first.x = x;
}
upd(a[i].second);
}
} const val_t &operator[](const string &s)const {
size_t i = 0;
for(auto x: s){
i = get_child(i, x);
if(a[i].first.x != x)
return _null;
}
return a[i].second;
}
}; trie<trie<int>> a; int main(){
#ifdef LOCAL
freopen("in.txt", "r", stdin);
#endif
ios::sync_with_stdio(false);
cin.tie(nullptr); int n, m;
cin >> n >> m; for(int i=0; i<n; i++){
string s;
int v;
cin >> s >> v; auto upd = [s, v](auto &val)mutable {
reverse(s.begin(), s.end());
val.insert(s, [v](auto &val){val=max(val, v);});
}; a.insert(s, upd);
} for(int i=0; i<m; i++){
string pre, suf;
cin >> pre >> suf;
reverse(suf.begin(), suf.end()); // error-prone
int res = a[pre][suf];
cout << (res? res: -1) << '\n';
}
return 0;
}

代码中用到了 generic lambda:

auto upd = [s, v](auto &val)mutable {
reverse(s.begin(), s.end());
val.insert(s, [v](auto &val){val=max(val, v);});
};

这是 C++ 14 引入的新特性,如果你使用的编译器尚不支持 C++ 14,可以将「lambda 表达式」改成「generic functor」。

hihoCoder #1656 前后缀查询的更多相关文章

  1. codeforces 579D D. "Or" Game(前后缀+贪心)

    题目链接: D. "Or" Game time limit per test 2 seconds memory limit per test 256 megabytes input ...

  2. Objective-C 【NSString-字符串比较&前后缀检查及搜索】

    ———————————————————————————————————————————NSString 字符串比较 #import <Foundation/Foundation.h> vo ...

  3. poj 2752 Seek the Name, Seek the Fame【KMP算法分析记录】【求前后缀相同的子串的长度】

    Seek the Name, Seek the Fame Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 14106   Ac ...

  4. [LeetCode] Prefix and Suffix Search 前后缀搜索

    Given many words, words[i] has weight i. Design a class WordFilter that supports one function, WordF ...

  5. Hibernate给表和字段设置前后缀及分隔符

    在<一口一口吃掉Hibernate(一)--使用SchemaExport生成数据表>中介绍了如何生成数据表.但是这只是最基本的.hibernate在生成或者操作数据库时,会受一些限制.比如 ...

  6. HDU 2594(求最长公共前后缀 kmp)

    题意是在所给的两个字符串中找最长的公共前后缀,即第一个字符串前缀和第二个字符串后缀的最长相等串. 思路是将两个字符串拼接在一起,然后直接套用 kmp 算法即可. 要注意用 next 会报编译错误,改成 ...

  7. poj 2752 求一个字符串所有的相同前后缀

    求一个字符串所有的相同前后缀Sample Input ababcababababcababaaaaaSample Output 2 4 9 181 2 3 4 5 #include <iostr ...

  8. HDU 2594 最长相同前后缀

    Sample Inputclintonhomerriemannmarjorie Sample Output0rie 3 输入两个字符串 ,求最长相同前后缀直接把两个字符串连接在一起求next就行了,唯 ...

  9. python 删除2天前后缀为.log的文件

    python脚本 删除2天前后缀为.log的文件 #!/usr/local/python/bin/python #-*-coding=utf8 -*- import time import os,sy ...

随机推荐

  1. CF Gym 100637K Microcircuits (DP)

    题意:给你n个点,将这些点放在一个环上,问你不相交的连k条线的方案数.(没有重点) 题解:dp[i][j]表示i个点连j条线的方案数,那么新加一个点i, 情况1,i没有和之前的点相连,方案数为dp[i ...

  2. CF Gym 100637J Superfactorial numeral system (构造)

    题意:给一个式子,ak,k>2时,0<=ak<k:ai都是整数,给你p,q让你求一组ak. 题解:构造,每次除掉q取整得到ai,然后减一减 #include<cstdio> ...

  3. 什么样子的WordPress网站更受搜索引擎欢迎

    网站的导航功能对于搜索引擎而言是非常重要的 网站的导航功能对于帮助用户迅速找到他们想要的内容来说是很重要的.它对帮助搜索引擎理解该网站有哪些重要内容同样非常重要.虽然百度的搜索结果都是指向每一个特定的 ...

  4. 四、filter和find函数的区别

    filter(): filter函数会返回data中为true那项的数组(即查询符合条件的数据) eg:data.filter((f)=>{ if(f[name]===item[name]){ ...

  5. 怎么在WEBSTORM中设置代码模板 Live Templates

    怎么在WEBSTORM中设置代码模板 Live Templates setting 里面 https://www.cnblogs.com/xinzaimengzai/p/9938464.html

  6. c++链表-双向链表+增删查改

    基于双向链表的增删改查和排序(C++实现) 双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱.所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前 ...

  7. JDBC连接数据库报错:java.sql.SQLException: The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more than one time zone. ......

    问题:Java程序使用JDBC连接MySQL数据库时,控制台报错如下: java.sql.SQLException: The server time zone value 'Öйú±ê׼ʱ¼ä' ...

  8. 在2d游戏中常用的向量方式

    function cc.exports.VectorRotateByAngle(vector,angle)--计算向量旋转后的向量,angle:正数逆时针,负输顺时针 angle = angle*ma ...

  9. 【two pointers 细节题】cf1041dD. Glider

    像这样细节老是打挂不行啊…… A plane is flying at a constant height of hh meters above the ground surface. Let's c ...

  10. java实现验证码功能

    java实现验证码功能 通过java代码实现验证码功能的一般思路: 一.通过java代码生成一张验证码的图片,将验证码的图片保存到项目中的指定文件中去,代码如下: package com.util; ...