题面

一个长度为 \(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. mybatis各阶段的详解

    1 本阶段的需要注意的几个点 1,首先是在核心配置文件里面的内容: 配置的顺序,不配则不用管,配则必须按顺序来!!!! properties?, settings?, typeAliases?, ty ...

  2. 溢出属性,定位,z-index,JS

    溢出属性 1.visible(默认值):使溢出内容展示 2.hidden:隐藏溢出内容且不出现滚动条 3.scroll:隐藏溢出容器的内容,溢出的内容可以通过滚动呈现 4.auto:与scroll没啥 ...

  3. CI/CD介绍以及jenkins安装 1.1

    一 .CI/CD介绍    互联网软件开发和发布,形成了一套流程标准,分为几个阶段:编码,构建,集成,测试,交付,部署  持续集成(continuous integration).持续交付(conti ...

  4. 个人冲刺(二)——体温上报app(二阶段)

    冲刺任务:完成app首页.第二页面和特殊情况的页面布局 activity_main.xml <?xml version="1.0" encoding="utf-8& ...

  5. 如何使用picGo+typora配置云笔记

    PicGo的使用 安装 picGo 2.3版本 (window可用)---官网有点慢,已经下载到个人仓库 https://gitee.com/lht1132950411/study/blob/mast ...

  6. 《Unix 网络编程》08:基本UDP套接字编程

    基本UDP套接字编程 系列文章导航:<Unix 网络编程>笔记 UDP 概述 流程图 recvfrom 和 sendto #include <sys/socket.h> ssi ...

  7. CF1485E Move and Swap

    题意:Move and Swap 很好的题呢 n个节点的树,根为1,所有叶子的深度都是D,一开始根节点上有两个颜色分别微R,B的球,你执行下列操作D-1次: 1.R点跳到子树内 2.B点跳到下一层的任 ...

  8. ClickHouse(01)什么是ClickHouse,ClickHouse适用于什么场景

    ClickHouse的由来 ClickHouse是什么数据库?ClickHouse速度有多快?应用场景是怎么样的?ClickHouse是关系型数据库吗?ClickHouse目前是很火爆的一款面向OLA ...

  9. Python中plt.plot()、plt.scatter()和plt.legend函数的用法示例

    参考:http://www.cppcns.com/jiaoben/python/471948.html https://blog.csdn.net/weixin_44825185/article/de ...

  10. Eureka入门

    一个Eureka中分为eureka server和eureka client.其中eureka server是作为服务的注册与发现中心.eureka client既可以作为服务的生产者,又可以作为服务 ...