题面

一个长度为 \(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 社论的更多相关文章

  1. @ConfigurationProperties(pref="")加载局部配置文件

    刚开始@ConfigurationProperties(文件名)直接在参数里加文件名,其实是配置前缀pref="前缀".加载局部配置文件是@PropertySource(value ...

  2. Chrome Switchs & Chrome Pref

    Chrome Switchs: https://chromium.googlesource.com/chromium/src/+/master/chrome/common/chrome_switche ...

  3. 丽泽普及2022交流赛day20 1/4社论

    目录 T1 正方形 T2 玩蛇 T3 嗷呜 T4 开车 T1 正方形 略 T2 玩蛇 略 T3 嗷呜 (插一个删一个?) 找出相同的,丢掉循环节 . 感觉非常离谱,,, 正确性存疑 正确性问 SoyT ...

  4. Minimax 社论

    目录 题面 题解 代码 Reference 题面 LOJ #2537 / 洛谷 P5298 「PKUWC2018」Minimax 一棵有根二叉树 \(\mathcal T\) . 定义结点 \(x\) ...

  5. 丽泽普及2022交流赛day22 无社论

    开始掉分模式 . T3 有人上费用流了???(id) 不用 TOC 了 . T1 暴力 T2 没看见 任意两圆不相交,gg 包含关系容易维护,特判相切 . 单调栈即可 T3 贪心 T4 神秘题

  6. 丽泽普及2022交流赛day21 社论

    A 暴力 . greater<double> -> greater<int> \(100\) -> \(50\) 代码丢了 . B dp . 考场上代码抢救一下就过 ...

  7. 丽泽普及2022交流赛day19 半社论

    目录 No Problem Str Not TSP 题面 题解 代码 Game 题面 题解 代码 No Problem 暴力 Str 存在循环节,大力找出来即可,长度显然不超过 \(10^3\) . ...

  8. 丽泽普及2022交流赛day18 社论

    A 暴力扫一遍 B 算法 0 似乎是二分 算法 1 随便贪心 C 算法 1 枚举一个点作为最大值 / 最小值,用单调栈维护其作为答案的左右端点即可轻易计算 . 时间复杂度 \(O(n)\) . 算法 ...

  9. 膜 社论(egg drop)

    题面 \(n\) 楼 \(m\) 个鸡蛋,从 \(k\) 楼及以上扔下去会碎,不能再测试 . 问至少需要扔几次确定 \(k\) . \(n\le 10^{18}\),\(m\le 64\) . 题解 ...

随机推荐

  1. 操作系统实现-printk

    博客网址:www.shicoder.top 微信:18223081347 欢迎加群聊天 :452380935 这一次我们来实现最基础,也是最常见的函数print,大家都知道这个是可变参数函数,那具体怎 ...

  2. 【算法】希尔排序(Shell Sort)(四)

    希尔排序(Shell Sort) 1959年Shell发明,第一个突破O(n2)的排序算法,是简单插入排序的改进版.它与插入排序的不同之处在于,它会优先比较距离较远的元素.希尔排序又叫缩小增量排序. ...

  3. 性能测试:tcpcopy

    简介 TCPCopy是一种请求复制(所有基于tcp的packets)工具,可以把在线流量导入到测试系统中去. 曾经应用于网易的广告投放系统,urs系统,nginx hmux协议等系统,避免了上线带来的 ...

  4. Python 生成图片验证码

    验证码图片生成 #!/usr/bin/env python # -*- coding: utf-8 -*- # refer to `https://bitbucket.org/akorn/wheezy ...

  5. Crontab在服务端进行设置定时执行任务

    Crontab简crontab是一个可以根据时间.日期.月份.星期的组合调度对重复任务的执行的守护进程.也可以讲Linux crontab是用来定期执行程序的命令. 当安装完成操作系统之后,默认便会启 ...

  6. python 的 @staticmethod和@classmethod和普通实例方法

    参考:https://www.huaweicloud.com/articles/12607084.html https://blog.csdn.net/qq_30708445/article/deta ...

  7. 为什么要使用TypeScript(Why Typescript?)

    客观原因 静态类型. 在编译期即可进行静态类型分析, 减少JS运行时类型错误. 语法功能强大 对于大型项目具有更好构建机制,加入了类.接口.泛型.模块等概念. 兼容JavaScript 与现存的Jav ...

  8. 高通sensor理解

    .1.高通为什么引入adsp? 2.adsp sensor 是如何工作起来的? 3.adsp 和ap 是如何通信的? 4.adsp 架构组成 解答: 1.高通在msm8960之前sensor 是挂在p ...

  9. canvas简易画布

    今天学习了canvas,利用它做了一个简易版的画板,校验自己所学的知识,分享出来以供大家学习指教.先上效果图. 主要是使用了canvas的stroke和clearReact来实现画板的绘画和橡皮擦功能 ...

  10. UiPathExcel读取操作

    一.Uipath操作Excel的相关基本概念 1.UiPath操作Excel的两组方法 App Integration > Excel   VS  System > File > W ...