Pref 社论
题面
一个长度为 \(k\) 字符串序列 \(s\) 是好的,当且仅当 \(\forall 1\le i<k\),有 \(B_i\) 既是 \(B_{i+1}\) 的前缀,又是 \(B_{i+1}\) 的后缀 .
给一个字符串序列 \(A\),求其最长好子序列 .
数据范围:\(\displaystyle \sum_k |A_k|\le 2\times 10^6\)
时限 \(2\ \rm s\),空限 \(512\rm\ MB\) .
题解
算法 1
考虑 dp .
令 \(dp_i\) 表示以 \(A_i\) 结尾的最长好序列,于是可以暴力转移 .
时间复杂度 \(O(n^3)\),期望 \(20\sim 40pts\) .
算法 2
考虑加速算法 \(1\) 中转移过程 .
字符串 Hash 处理每个子串的 border,同时构建映射 \(\mathrm M:\,border\to dp\) .
一轮 dp 可以线性完成,映射可以考虑两种实现方式
| 方式编号 | 表现 \(1\) | 表现 \(2\) | 时间复杂度 | 
|---|---|---|---|
| \(1\) | std::map | 平衡树 | \(O(n\log n)\) | 
| \(2\) | std::unordered_map | Hash Table | \(O(n)\) | 
期望 \(100pts\) .
算法 3(标答)
记 \(\overline s\) 为 \(s\) 逆序排成的字符串 .
于是 \(s\) 是 \(t\) 的后缀等价于 \(\overline s\) 是 \(\overline t\) 的前缀 .
现在我们有两个前缀关系,建 Trie 树并且在 Trie 树上 dp 即可 .
期望 \(100pts\) .
代码
算法 1
20pts(by jijidawang)
using namespace std;
typedef long long ll;
const int N = 1e6 + 500;
int n;
ll p, dp[N];
string s[N];
inline bool pure_chk(string a, string b)
{
	int la = a.length(), lb = b.length();
	if (la > lb) return false;
	for (int i=0; i<la; i++)
		if (a[i] != b[i]) return false;
	return true;
}
inline bool chk(string a, string b)
{
	bool ans = pure_chk(a, b);
	reverse(b.begin(), b.end());
	return ans & pure_chk(a, b);
}
int main()
{
	scanf("%d", &n);
	for (int i=1; i<=n; i++) cin >> s[i];
	dp[1] = 1;
	for (int i=2; i<=n; i++)
		for (int j=1; j<i; j++)
			if (chk(s[j], s[i])) dp[i] = max(dp[i], dp[j]+1);
	ll ans = 0;
	for (int i=1; i<=n; i++) ans = max(ans, dp[i]);
	printf("%lld\n", ans);
	return 0;
}
40pts(by Rolling_Star)
using namespace std;
int n,dp[2000001];
string s[2000001];
bool flag;
inline bool check(int x,int y);
int main()
{
    cin>>n;
    for(register int i=1;i<=n;i++)
        cin>>s[i];
    int ans=0;
    dp[1]=1;
    for(register int i=2;i<=n;++i)
    {
        dp[i]=1;
        for(register int j=1;j<=i-1;++j)
            if(s[i].size()>=s[j].size())
                if(check(i,j))
                    dp[i]=max(dp[i],dp[j]+1);
        ans=max(ans,dp[i]);
    }
    cout<<ans;
}
inline bool check(int x,int y)
{
    for(register int i=0;i<s[y].size();++i)
        if(s[y][i]!=s[x][i])
            return false;
    for(register int i=s[x].size()-s[y].size(),j=0;j<s[y].size();++i,++j)
        if(s[y][j]!=s[x][i])
            return false;
    return true;
}
算法 2
using namespace std;
const int N = 1e6 + 500;
typedef long long ll;
typedef char str[N];
const ll P = 1e9+7, base = 131;
int n;
ll pb[N];
str s;
map<ll, int> dp;
int main()
{
	scanf("%d", &n);
	pb[0] = 1;
	for (int i=1; i<N; i++) pb[i] = pb[i-1] * base % P;
	int ans = 0;
	for (int i=1; i<=n; i++)
	{
		scanf("%s", s+1); int l = strlen(s+1);
		ll p=0, ss=0; int H=0;
		for (int j=1; j<=l; j++)
		{
			p = (p*base % P + s[j]) % P;
			ss = (ss + s[l-j+1]*pb[j-1] % P) % P;
			if (p == ss) H = max(H, dp[p]);
		}
		dp[p] = max(dp[p], H+1);
		ans = max(ans, dp[p]);
	} printf("%d\n", ans);
	return 0;
}
算法 3
Pref 社论的更多相关文章
- @ConfigurationProperties(pref="")加载局部配置文件
		刚开始@ConfigurationProperties(文件名)直接在参数里加文件名,其实是配置前缀pref="前缀".加载局部配置文件是@PropertySource(value ... 
- Chrome Switchs & Chrome Pref
		Chrome Switchs: https://chromium.googlesource.com/chromium/src/+/master/chrome/common/chrome_switche ... 
- 丽泽普及2022交流赛day20 1/4社论
		目录 T1 正方形 T2 玩蛇 T3 嗷呜 T4 开车 T1 正方形 略 T2 玩蛇 略 T3 嗷呜 (插一个删一个?) 找出相同的,丢掉循环节 . 感觉非常离谱,,, 正确性存疑 正确性问 SoyT ... 
- Minimax 社论
		目录 题面 题解 代码 Reference 题面 LOJ #2537 / 洛谷 P5298 「PKUWC2018」Minimax 一棵有根二叉树 \(\mathcal T\) . 定义结点 \(x\) ... 
- 丽泽普及2022交流赛day22 无社论
		开始掉分模式 . T3 有人上费用流了???(id) 不用 TOC 了 . T1 暴力 T2 没看见 任意两圆不相交,gg 包含关系容易维护,特判相切 . 单调栈即可 T3 贪心 T4 神秘题 
- 丽泽普及2022交流赛day21 社论
		A 暴力 . greater<double> -> greater<int> \(100\) -> \(50\) 代码丢了 . B dp . 考场上代码抢救一下就过 ... 
- 丽泽普及2022交流赛day19 半社论
		目录 No Problem Str Not TSP 题面 题解 代码 Game 题面 题解 代码 No Problem 暴力 Str 存在循环节,大力找出来即可,长度显然不超过 \(10^3\) . ... 
- 丽泽普及2022交流赛day18 社论
		A 暴力扫一遍 B 算法 0 似乎是二分 算法 1 随便贪心 C 算法 1 枚举一个点作为最大值 / 最小值,用单调栈维护其作为答案的左右端点即可轻易计算 . 时间复杂度 \(O(n)\) . 算法 ... 
- 膜 社论(egg drop)
		题面 \(n\) 楼 \(m\) 个鸡蛋,从 \(k\) 楼及以上扔下去会碎,不能再测试 . 问至少需要扔几次确定 \(k\) . \(n\le 10^{18}\),\(m\le 64\) . 题解 ... 
随机推荐
- 操作系统实现-printk
			博客网址:www.shicoder.top 微信:18223081347 欢迎加群聊天 :452380935 这一次我们来实现最基础,也是最常见的函数print,大家都知道这个是可变参数函数,那具体怎 ... 
- 【算法】希尔排序(Shell Sort)(四)
			希尔排序(Shell Sort) 1959年Shell发明,第一个突破O(n2)的排序算法,是简单插入排序的改进版.它与插入排序的不同之处在于,它会优先比较距离较远的元素.希尔排序又叫缩小增量排序. ... 
- 性能测试:tcpcopy
			简介 TCPCopy是一种请求复制(所有基于tcp的packets)工具,可以把在线流量导入到测试系统中去. 曾经应用于网易的广告投放系统,urs系统,nginx hmux协议等系统,避免了上线带来的 ... 
- Python 生成图片验证码
			验证码图片生成 #!/usr/bin/env python # -*- coding: utf-8 -*- # refer to `https://bitbucket.org/akorn/wheezy ... 
- Crontab在服务端进行设置定时执行任务
			Crontab简crontab是一个可以根据时间.日期.月份.星期的组合调度对重复任务的执行的守护进程.也可以讲Linux crontab是用来定期执行程序的命令. 当安装完成操作系统之后,默认便会启 ... 
- python 的 @staticmethod和@classmethod和普通实例方法
			参考:https://www.huaweicloud.com/articles/12607084.html https://blog.csdn.net/qq_30708445/article/deta ... 
- 为什么要使用TypeScript(Why Typescript?)
			客观原因 静态类型. 在编译期即可进行静态类型分析, 减少JS运行时类型错误. 语法功能强大 对于大型项目具有更好构建机制,加入了类.接口.泛型.模块等概念. 兼容JavaScript 与现存的Jav ... 
- 高通sensor理解
			.1.高通为什么引入adsp? 2.adsp sensor 是如何工作起来的? 3.adsp 和ap 是如何通信的? 4.adsp 架构组成 解答: 1.高通在msm8960之前sensor 是挂在p ... 
- canvas简易画布
			今天学习了canvas,利用它做了一个简易版的画板,校验自己所学的知识,分享出来以供大家学习指教.先上效果图. 主要是使用了canvas的stroke和clearReact来实现画板的绘画和橡皮擦功能 ... 
- UiPathExcel读取操作
			一.Uipath操作Excel的相关基本概念 1.UiPath操作Excel的两组方法 App Integration > Excel VS System > File > W ... 
