cv3160 最长公共子串(SAM)
2018-01-28 15:50
211 查看
题目链接
分析:
AA串建立一个SAMSAM
用BB串在SAMSAM上匹配
能匹配到的最远结点(到rootroot的距离)就是最长公共子串
如果匹配不上的时候,我们直接通过parentparent跳到ta的“失配”上
分析:
AA串建立一个SAMSAM
用BB串在SAMSAM上匹配
能匹配到的最远结点(到rootroot的距离)就是最长公共子串
如果匹配不上的时候,我们直接通过parentparent跳到ta的“失配”上
tip
虽然SAMSAM的空间是O(n)O(n),但是在开数组的时候是大小要到n∗2n∗2#include<cstdio> #include<cstring> #include<iostream> using namespace std; const int N=100003; int ch[N<<1][26],fa[N<<1],sz=1,last=1,root=1,dis[N<<1]; char a ,b ; void insert(int x) { int pre=last,now=++sz; last=now; dis[now]=dis[pre]+1; for (;pre&&!ch[pre][x];pre=fa[pre]) ch[pre][x]=now; //找Parent树上有没有这个结点 if (!pre) fa[now]=root; else { int q=ch[pre][x]; //找了一个祖先 if (dis[q]==dis[pre]+1) fa[now]=q; else { int nows=++sz; dis[nows]=dis[pre]+1; memcpy(ch[nows],ch[q],sizeof(ch[nows])); fa[nows]=fa[q]; fa[now]=fa[q]=nows; for (;pre&&ch[pre][x]==q;pre=fa[pre]) ch[pre][x]=nows; } } } void solve() { int len=strlen(b+1),ans=0,now=root,tmp=0; for (int i=1;i<=len;i++) { int x=b[i]-'a'; if (ch[now][x]) now=ch[now][x],tmp++; else { while (now&&!ch[now][x]) now=fa[now]; if (!now) now=1,tmp=0; else { tmp=dis[now]+1; now=ch[now][x]; } } ans=max(ans,tmp); } printf("%d",ans); } int main() { scanf("%s",a+1); scanf("%s",b+1); for (int i=1;i<strlen(a+1);i++) insert(a[i]-'a'); solve(); return 0; }
相关文章推荐
- codevs 3160 最长公共子串(SAM)
- 【SAM】codevs3160-最长公共子串
- code vs 3160 最长公共子串(后缀自动机)
- poj3080,poj3450 多个字符串求最长公共子串问题 KMP,SA,SAM:
- 3160 最长公共子串
- [POJ2774]Long Long Message [CodeVS3160]最长公共子串 做题笔记
- Codevs 3160 最长公共子串
- SPOJ 1811. Longest Common Substring (LCS,两个字符串的最长公共子串, 后缀自动机SAM)
- 从最长公共子串到后缀自动机(LCS->SAM)
- CODE【VS】 3160 最长公共子串 (后缀数组)
- SPOJ 1811. Longest Common Substring (LCS,两个字符串的最长公共子串, 后缀自动机SAM)
- codevs 3160 最长公共子串
- 【CodeVS 3160】最长公共子串
- 后缀数组 3160 最长公共子串
- 【wikioi】3160 最长公共子串(后缀自动机)
- CODE【VS】3160 最长公共子串 (后缀自动机)
- 【codevs3160】最长公共子串 后缀数组
- [codevs3160]最长公共子串解题报告|后缀自动机
- codevs 3160 最长公共子串
- [CODEVS3160]最长公共子串|后缀数组|后缀自动机