[SPOJ-LCS]Longest Common Substring

Posted skylee的OI博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[SPOJ-LCS]Longest Common Substring相关的知识,希望对你有一定的参考价值。

题目大意:
  求两个字符串的LCS。

思路:
  对其中一个字符串构建SAM,然后用另一个字符串在里面匹配,按照SAM的边一直往下走,匹配到的连续的字符数就是公共字串的长度。

 1 #include<string>
 2 #include<cstring>
 3 #include<iostream>
 4 std::string s,t;
 5 class SuffixAutomaton {
 6     private:
 7         static const int SIGMA_SIZE=26;
 8         int idx(const char ch) {
 9             return ch-a;
10         }
11         struct State {
12             State *link,*go[SIGMA_SIZE];
13             int len;
14             State(const int l) {
15                 link=NULL;
16                 len=l;
17                 memset(go,0,sizeof go);
18             }
19         };
20         State *root,*last;
21         void extend(const char ch) {
22             int w=idx(ch);
23             State *p=last;
24             State *new_p=new State(p->len+1);
25             while(p!=NULL&&p->go[w]==NULL) {
26                 p->go[w]=new_p;
27                 p=p->link;
28             }
29             if(p==NULL) {
30                 new_p->link=root;
31             } else {
32                 State *q=p->go[w];
33                 if(q->len==p->len+1) {
34                     new_p->link=q;
35                 } else {
36                     State *new_q=new State(p->len+1);
37                     memcpy(new_q->go,q->go,sizeof q->go);
38                     new_q->link=q->link;
39                     q->link=new_p->link=new_q;
40                     while(p!=NULL&&p->go[w]==q) {
41                         p->go[w]=new_q;
42                         p=p->link;
43                     }
44                 }
45             }
46             last=new_p;
47         }
48     public:
49         void build(std::string &s) {
50             last=root=new State(0);
51             for(std::string::iterator i=s.begin();i<s.end();i++) extend(*i);
52         }
53         int match(std::string &s) {
54             int ret=0,tmp=0;
55             State *p=root;
56             for(std::string::iterator i=s.begin();i<s.end();i++) {
57                 int w=idx(*i);
58                 if(p!=NULL&&p->go[w]!=NULL) {
59                     p=p->go[w];
60                     tmp++;
61                 } else {
62                     while(p!=NULL&&p->go[w]==NULL) p=p->link;
63                     if(p==NULL) {
64                         p=root;
65                         tmp=0;
66                     } else {
67                         tmp=p->len+1;
68                         p=p->go[w];
69                     }
70                 }
71                 ret=std::max(ret,tmp);
72             }
73             return ret;
74         }
75 };
76 SuffixAutomaton sam;
77 int main() {
78     std::ios_base::sync_with_stdio(false);
79     std::cin.tie(NULL);
80     std::cin>>s;
81     sam.build(s);
82     std::cin>>s;
83     std::cout<<sam.match(s)<<std::endl;
84     return 0;
85 }

 

以上是关于[SPOJ-LCS]Longest Common Substring的主要内容,如果未能解决你的问题,请参考以下文章

Longest Common Prefix

14. Longest Common Prefix

1143. Longest Common Subsequence

1143. Longest Common Subsequence

leetcode14. longest common prefix

LintCode Longest Common Subsequence