SPOJ1812 Longest Common Substring II
Longest Common Substring II
给定n个串,求它们的最长公共子串。
at most 10 lines,no more than 100000
iwt的题解
本题容易看出就是分别将所有串的所有匹配长度记录在状态上,然后取所有串记录值的min,后再对所有状态取max。
但是不要忘记了一点:更新parent树的祖先。
为什么呢?首先如果子树被匹配过了,那么长度一定大于任意祖先匹配的长度(甚至有些祖先匹配长度为0!为什么呢,因为我们在匹配的过程中,只是找到一个子串,可能还遗漏了祖先没有匹配到,这样导致了祖先的记录值为0,那么在对对应状态取min的时候会取到0,这样就wa了。而且注意,如果匹配到了当前节点,那么祖先们一定都可以赋值为祖先的length!因为当前节点的length大于任意祖先。(
比如数据
acbbc
bc
ac
答案应该是1没错吧。如果没有更新祖先,那么答案会成0。
这个多想想就行了。
所以以后记住:对任意多串匹配时,凡是对同一个状态取值时,要注意当前状态的子树是否比当前状态记录的值优。
时间复杂度:线性。
co int N=2e5; namespace SAM { int tot,last; int ch[N][26],fail[N]={-1},len[N]; void extend(int k) { int cur=++tot; len[cur]=len[last]+1; int p=last; while(~p&&!ch[p][k]) { ch[p][k]=cur; p=fail[p]; } if(p==-1) fail[cur]=0; else { int q=ch[p][k]; if(len[q]==len[p]+1) fail[cur]=q; else { int clone=++tot; std::copy(ch[q],ch[q]+26,ch[clone]); fail[clone]=fail[q],len[clone]=len[p]+1; while(~p&&ch[p][k]==q) { ch[p][k]=clone; p=fail[p]; } fail[cur]=fail[q]=clone; } } last=cur; } int c[N],id[N],mx[N],arr[N]; void build(char s[],int n) { for(int i=0;i<n;++i) extend(s[i]-'a'); for(int i=0;i<=tot;++i) ++c[len[i]]; for(int i=1;i<=n;++i) c[i]+=c[i-1]; for(int i=0;i<=tot;++i) id[--c[len[i]]]=i; // edit 1:--c for 0 std::copy(len,len+tot+1,mx); } void find(char s[],int n) { int p=0,l=0; for(int i=0;i<n;++i) { int k=s[i]-'a'; if(ch[p][k]) p=ch[p][k],++l; else { while(~p&&!ch[p][k]) p=fail[p]; if(p==-1) p=l=0; else l=len[p]+1,p=ch[p][k]; } arr[p]=std::max(arr[p],l); } for(int i=tot;i>=0;--i) { int p=id[i]; mx[p]=std::min(mx[p],arr[p]); if(arr[p]&&fail[p]) arr[fail[p]]=len[fail[p]]; arr[p]=0; } } int getans() { int ans=0; for(int i=0;i<=tot;++i) ans=std::max(ans,mx[i]); return ans; } } char buf[N]; int main() { // freopen(".in","r",stdin); // freopen(".out","w",stdout); scanf("%s",buf); SAM::build(buf,strlen(buf)); while(~scanf("%s",buf)) SAM::find(buf,strlen(buf)); printf("%d\n",SAM::getans()); return 0; }
静渊以有谋,疏通而知事。
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从二进制到误差:逐行拆解C语言浮点运算中的4008175468544之谜
· .NET制作智能桌面机器人:结合BotSharp智能体框架开发语音交互
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· Windows桌面应用自动更新解决方案SharpUpdater5发布
· 我的家庭实验室服务器集群硬件清单
· C# 13 中的新增功能实操
· Supergateway:MCP服务器的远程调试与集成工具
· Vue3封装支持Base64导出的电子签名组件