zoukankan      html  css  js  c++  java
  • [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 }
  • 相关阅读:
    第6章 LVM详解
    第5章 Linux上管理文件系统
    第4章 ext文件系统机制原理剖析
    第3章 Linux上文件的权限管理
    第2章 系统用户/组管理(2) su和sudo
    第2章 细说Linux系统用户/组管理(1)
    cpio用法详细说明
    Linux find运行机制详解
    第1章 Linux文件类基础命令
    PXE+kickstart无人值守安装CentOS 6
  • 原文地址:https://www.cnblogs.com/skylee03/p/7513430.html
Copyright © 2011-2022 走看看