题目链接:点击查看

题目大意:给出n个字符串,求出最长公共子串的长度

题目分析:之前做过了求两个字符串最长公共子串的长度,相对来说那个题目还算是比较简单入门的,这个题目就稍微有点加大难度了,其实难度也是在可以接受的范围之内,类比于求两个字符串的最长公共子串,我们其实一样可以对一个字符串求出SAM,然后让剩下n-1个字符串在SAM上维护最大匹配长度,同时在SAM的每个节点都维护一个当前字符串可以匹配的最大值,显然最后应该维护每个节点所有最大值中的最小值作为该节点可以匹配的最大长度,最后的答案也应该是每个节点可以匹配的最大长度中的最大值了

不过以此延伸出一个问题来,因为每个节点会通过后缀链接和父节点相连,也就是说如果可以走到一个节点时,其父节点也必定是可以到达的,所以我们需要实时维护父节点的最大值,但这也必须保证我们在遍历SAM时自底向上遍历才行,为了解决这个问题,我们可以在构造出SAM后进行拓扑排序,其实这个拓扑排序还是相对简单的,因为只需要对于每个节点的len进行排序就好了,利用桶排序就可以完成,在更新时按照拓扑序倒着更新就好了

代码:

#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<unordered_map>
using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=1e5+100;char s[N];int tot=1,last=1,id[N<<1],tong[N<<1],mmax[N<<1],mmin[N<<1];struct Node
{int ch[26];int fa,len;
}st[N<<1];void add(int x)
{int p=last,np=last=++tot;st[np].len=st[p].len+1;while(p&&!st[p].ch[x])st[p].ch[x]=np,p=st[p].fa;if(!p)st[np].fa=1;else{int q=st[p].ch[x];if(st[p].len+1==st[q].len)st[np].fa=q;else{int nq=++tot;st[nq]=st[q]; st[nq].len=st[p].len+1;st[q].fa=st[np].fa=nq;while(p&&st[p].ch[x]==q)st[p].ch[x]=nq,p=st[p].fa;//向上把所有q都替换成nq}}
}void radix_sort()
{for(int i=1;i<=tot;i++)tong[st[i].len]++;for(int i=1;i<=tot;i++)tong[i]+=tong[i-1];for(int i=1;i<=tot;i++)id[tong[st[i].len]--]=i;
}void solve()
{memset(mmax,0,sizeof(mmax));int len=strlen(s),k=1,cnt=0;for(int i=0;i<len;i++){int to=s[i]-'a';if(st[k].ch[to]){cnt++;k=st[k].ch[to];mmax[k]=max(mmax[k],cnt);}else{while(k&&!st[k].ch[to])k=st[k].fa;if(k){cnt=st[k].len+1;k=st[k].ch[to];mmax[k]=max(mmax[k],cnt);}else{cnt=0;k=1;}}}//以上是完成求两个字符串的最长公共子串的基操for(int i=tot;i>=1;i--){int cur=id[i],fa=st[cur].fa;mmax[fa]=max(mmax[fa],min(st[fa].len,mmax[cur]));//维护父节点的最大值mmin[cur]=min(mmin[cur],mmax[cur]);//维护每个节点的最小值}
}int main()
{
//  freopen("input.txt","r",stdin);
//  ios::sync_with_stdio(false);scanf("%s",s);int len=strlen(s);for(int i=0;i<len;i++)add(s[i]-'a');radix_sort();for(int i=1;i<=tot;i++)mmin[i]=st[i].len;while(scanf("%s",s)!=EOF)solve();int ans=0;for(int i=1;i<=tot;i++)ans=max(ans,mmin[i]);printf("%d\n",ans);return 0;
}

SPOJ - LCS2 Longest Common Substring II(后缀自动机)相关推荐

  1. SPOJ 1812 LCS2 - Longest Common Substring II (后缀自动机)【两种做法】

    SPOJ 1812 LCS2 - Longest Common Substring II (后缀自动机)[两种做法] 手动博客搬家: 本文发表于20181217 23:54:35, 原地址https: ...

  2. SPOJ 1812 LCS2 - Longest Common Substring II (后缀自动机、状压DP)

    手动博客搬家: 本文发表于20181217 23:54:35, 原地址https://blog.csdn.net/suncongbo/article/details/85058680 人生第一道后缀自 ...

  3. Spoj LCS2 - Longest Common Substring II

    题目描述 A string is finite sequence of characters over a non-empty finite set Σ. In this problem, Σ is ...

  4. 后缀自动机求多个串的最长公共子串+拓补排序讲解+LCS2 - Longest Common Substring II

    网上所有关于后缀自动机拓补排序的文章,都默认读者会拓补排序,简直了. 后缀自动机的拓补排序,就是按照长度进行排序,在进行特定操作的时候,通过较长的后缀来更新较短的后缀.那么也就是通过拓补排序中排名靠后 ...

  5. SPOJ1812 LCS2 - Longest Common Substring II(SAM)

    题目链接 分析: SAM求多串最长公共子串 详解戳这里 #include<cstdio> #include<cstring> #include<iostream>u ...

  6. spoj Longest Common Substring II

    Longest Common Substring II SPOJ - LCS2 求10个串的LCS /*1.用第一个串建立后缀自动机2.len[s] 表示状态s 所能代表的字符串的最大长度mx[s] ...

  7. SPOJ LCS Longest Common Substring

    A string is finite sequence of characters over a non-empty finite set Σ. In this problem, Σ is the s ...

  8. SPOJ - LCS Longest Common Substring(后缀自动机)

    题目链接:点击查看 题目大意:给出两个字符串,求出其最长公共子串的长度 题目分析:可以对第一个字符串建立SAM,然后令第二个字符串在建好的SAM上跑就好了,如果遇到不能跑的点,就往上折返直到找到可以继 ...

  9. JavaScript实现longest Common Substring最长公共子串算法(附完整源码)

    JavaScript实现longest Common Substring最长公共子串算法(附完整源码) longestCommonSubstring.js完整源代码 longestCommonSubs ...

最新文章

  1. VS Code配置PHP XDebug
  2. 深度学习综述:Hinton、Yann LeCun和Bengio经典重读
  3. 失败的Omni协议与继续前行的虫洞协议
  4. bootstrap 标题居中加颜色_BootStrap从基础到项目实战_第1季_03章_01_CSS样式之栅格布局...
  5. python真的超过java了吗-Python为什么突然就火了呢?竟然还超过了java
  6. C语言经典例14-将一个正整数分解质因数
  7. Android中获取应用程序(包)的信息-----PackageManager的使用(一)
  8. leetcode 1046. 最后一块石头的重量(堆)
  9. Qt实现界面的窗口的局部动态添加并布局
  10. Python 数据科学手册 5.6 线性回归
  11. CentOS Linux解决Device eth0 does not seem to be present【转】
  12. THINKPHP3文件缓存管理
  13. 求字符串中对称的子字符串的最大长度
  14. 创业挑战杯获奖作品范例_2017年挑战杯大学生创业大赛优秀作品
  15. 睡觉计算机主机在身旁好么,笔记本电脑的睡眠和休眠之间有什么区别
  16. 网站挂马检测 php,Python实现的检测网站挂马程序
  17. 五、SPR 单一职责
  18. vue-pdf插件import引入时报错
  19. 无盘新手大本营(转)
  20. Linux桌面录屏分享

热门文章

  1. 共享数据库、共享数据表
  2. Spring 工厂的相关的方法
  3. 策略模式Strategy Pattern应用场景
  4. SasSHRM中基于shiro的认证授权:系统微服务配置shiro
  5. 数据库-数据库的介绍
  6. StringBuilder的构造方法和append方法
  7. SpringBoot高级-消息-@RabbitListener@EnableRabbit
  8. spring项目搭建-注册对象到容器测试
  9. springioc注解版运行效果演示
  10. matlab plot subplot,Matlab使用subplot合并子图