[SPOJ-LCS2]Longest Common Substring II

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

思路:
  对于第一个字符串构造SAM,然后把后面的字符串放在SAM中匹配,对于同一个字符串匹配到的同一个状态,记录其匹配长度之max,
  然后对于不同的字符串匹配到的同一个状态,记录其匹配长度之min,然后对于所有的状态取max。
  然而这样只能过9个点,第10个点会WA,原因是如果不同的字符串匹配到的同一个字串,可能并不在SAM的同一个状态上,
  因此要将这些值与它的parent(程序中的link)共享(不需要往下传,否则会TLE,因为只要下面的往上传过,不管怎样都能在上面取到max)。
  我们可以沿着link一直往上跳,同时更新,然后就TLE了。
  考虑按照拓扑序(状态加入的SAM顺序)DP,对于每个状态,只要更新一次就可以,其余的状态都可以递推得到。
  由于STL用得太多,常数巨大,跑了200ms,但还是勉强进了VJudge的Leaderboard(Rank50),Rank49都只有80ms。
  关掉I/O同步以后也跑了180ms。

 

  1 #include<string>
  2 #include<vector>
  3 #include<iostream>
  4 const int inf=0x7fffffff;
  5 std::string s;
  6 class SuffixAutomaton {
  7     private:
  8         static const int SIGMA_SIZE=26,N=10;
  9         struct State {
 10             State *link,*go[SIGMA_SIZE];
 11             int len,maxlen[N];
 12             State(const int l) {
 13                 link=nullptr;
 14                 std::fill(&go[0],&go[SIGMA_SIZE],nullptr);
 15                 std::fill(&maxlen[0],&maxlen[N],0);
 16                 maxlen[0]=inf;
 17                 len=l;
 18             }
 19         };
 20         State *root,*last;
 21         int idx(const int ch) {
 22             return ch-'a';
 23         }
 24         std::vector<State*> v;
 25         void extend(const char ch) {
 26             const int w=idx(ch);
 27             State *p=last;
 28             State *new_p=new State(p->len+1);
 29             v.push_back(new_p);
 30             while(p!=nullptr&&p->go[w]==nullptr) {
 31                 p->go[w]=new_p;
 32                 p=p->link;
 33             }
 34             if(p==nullptr) {
 35                 new_p->link=root;
 36             } else {
 37                 State *q=p->go[w];
 38                 if(q->len==p->len+1) {
 39                     new_p->link=q;
 40                 } else {
 41                     State *new_q=new State(p->len+1);
 42                     v.push_back(new_q);
 43                     std::copy(&q->go[0],&q->go[SIGMA_SIZE],new_q->go);
 44                     new_q->link=q->link;
 45                     new_p->link=q->link=new_q;
 46                     while(p!=nullptr&&p->go[w]==q) {
 47                         p->go[w]=new_q;
 48                         p=p->link;
 49                     }
 50                 }
 51             }
 52             last=new_p;
 53         }
 54     public:
 55         int cnt;
 56         void build(std::string &s) {
 57             root=last=new State(0);
 58             for(std::string::iterator i=s.begin();i<s.end();i++) extend(*i);
 59         }
 60         void match(std::string &s) {
 61             cnt++;
 62             State *p=root;
 63             int tmp=0;
 64             for(std::string::iterator i=s.begin();i<s.end();i++) {
 65                 const int w=idx(*i);
 66                 if(p->go[w]!=nullptr) {
 67                     p=p->go[w];
 68                     tmp++;
 69                 } else {
 70                     while(p!=nullptr&&p->go[w]==nullptr) {
 71                         p=p->link;
 72                     }
 73                     if(p==nullptr) {
 74                         tmp=0;
 75                         p=root;
 76                     } else {
 77                         tmp=p->len+1;
 78                         p=p->go[w];
 79                     }
 80                 }
 81                 p->maxlen[cnt]=std::max(p->maxlen[cnt],tmp);
 82             }
 83             for(std::vector<State*>::iterator i=v.begin();i!=v.end();i++) {
 84                 State *p=*i,*q=(*i)->link;
 85                 if(q!=nullptr&&q->maxlen[cnt]!=p->maxlen[cnt]) {
 86                     q->maxlen[cnt]=std::max(q->maxlen[cnt],std::min(p->maxlen[cnt],q->len));
 87                 }
 88             }
 89             for(std::vector<State*>::iterator i=v.begin();i!=v.end();i++) {
 90                 State *p=*i;
 91                 p->maxlen[0]=std::min(p->maxlen[0],p->maxlen[cnt]);
 92             }
 93         }
 94         int lcs() {
 95             int ret=0;
 96             for(std::vector<State*>::iterator i=v.begin();i!=v.end();i++) {
 97                 State *p=*i;
 98                 ret=std::max(ret,p->maxlen[0]);
 99             }
100             return ret;
101         }
102 };
103 SuffixAutomaton sam;
104 int main() {
105     std::ios_base::sync_with_stdio(false);
106     std::cin.tie(NULL); 
107     std::cin>>s;
108     sam.build(s);
109     while(std::cin>>s) sam.match(s);
110     std::cout<<sam.lcs()<<std::endl;
111     return 0;
112 }

 

转载于:https://www.cnblogs.com/skylee03/p/7513430.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值