zoukankan      html  css  js  c++  java
  • [POI2000]Repetitions

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

    思路:
      同SPOJ-LCS2,不过因为SPOJ上数据比较水,当时用错误的写法过掉了,这次用正确的写法重新过了一遍。
      拓扑排序按照每个状态的len值,用计数排序实现。
      每个状态往上更新时,应该对std::min(s[p].maxlen,s[q].len)取max(每个状态能匹配的最长子串长度不超过len)。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 const int inf=0x7fffffff;
      5 const int LEN=2001;
      6 int n;
      7 char s[LEN];
      8 class SuffixAutomaton {
      9     private:
     10         static const int SIGMA_SIZE=26;
     11         struct State {
     12             int len,link,go[SIGMA_SIZE],maxlen,min;
     13         };
     14         int sz,root,last,len;
     15         int cnt[LEN],top[LEN<<1];
     16         State s[LEN<<1];
     17         int newState(const int l) {
     18             sz++;
     19             s[sz].len=l;
     20             s[sz].min=inf;
     21             return sz;
     22         }
     23         int idx(const char ch) {
     24             return ch-'a';
     25         }
     26         void extend(const char ch) {
     27             int w=idx(ch);
     28             int p=last;
     29             int new_p=newState(s[p].len+1);
     30             while(p&&!s[p].go[w]) {
     31                 s[p].go[w]=new_p;
     32                 p=s[p].link;
     33             }
     34             if(!p) {
     35                 s[new_p].link=root;
     36                 s[root].go[w]=new_p;
     37             } else {
     38                 int q=s[p].go[w];
     39                 if(s[q].len==s[p].len+1) {
     40                     s[new_p].link=q;
     41                 } else {
     42                     int new_q=newState(s[p].len+1);
     43                     memcpy(s[new_q].go,s[q].go,sizeof s[q].go);
     44                     s[new_q].link=s[q].link;
     45                     s[q].link=s[new_p].link=new_q;
     46                     while(p&&s[p].go[w]==q) {
     47                         s[p].go[w]=new_q;
     48                         p=s[p].link;
     49                     }
     50                 }
     51             }
     52             last=new_p;
     53         }
     54     public:
     55         void build(char str[]) {
     56             root=last=newState(0);
     57             len=strlen(str);
     58             for(int i=0;str[i];i++) extend(str[i]);
     59         }
     60         void top_sort() {
     61             for(int i=1;i<=sz;i++) cnt[s[i].len]++;
     62             for(int i=len;i;i--) cnt[i-1]+=cnt[i];
     63             for(int i=1;i<=sz;i++) top[cnt[s[i].len]--]=i;
     64         }
     65         void match(char str[]) {
     66             int p=root,tmp=0;
     67             for(int i=0;str[i];i++) {
     68                 int w=idx(str[i]);
     69                 if(s[p].go[w]) {
     70                     tmp++;
     71                     p=s[p].go[w];
     72                 } else {
     73                     while(p&&!s[p].go[w]) {
     74                         p=s[p].link;
     75                     }
     76                     if(!p) {
     77                         tmp=0;
     78                         p=root;
     79                     } else {
     80                         tmp=s[p].len+1;
     81                         p=s[p].go[w];
     82                     }
     83                 }
     84                 s[p].maxlen=std::max(s[p].maxlen,tmp);
     85             }
     86             for(int i=1;i<=sz;i++) {
     87                 int p=top[i],q=s[p].link;
     88                 s[q].maxlen=std::max(s[q].maxlen,std::min(s[p].maxlen,s[q].len));
     89                 s[p].min=std::min(s[p].min,s[p].maxlen);
     90                 s[p].maxlen=0;
     91             }
     92         }
     93         int lcs() {
     94             int ret=0;
     95             for(int i=1;i<=sz;i++) ret=std::max(ret,s[i].min);
     96             return ret;
     97         }
     98 };
     99 SuffixAutomaton sam;
    100 int main() {
    101     scanf("%d",&n);
    102     scanf("%s",s);
    103     sam.build(s);
    104     sam.top_sort();
    105     for(int i=2;i<=n;i++) {
    106         scanf("%s",s);
    107         sam.match(s);
    108     }
    109     printf("%d
    ",sam.lcs());
    110     return 0;
    111 } 
  • 相关阅读:
    信息安全算法
    另类装载问题
    分治法快速排序
    动态规划最长公共子序列
    java网络编程1
    Jndi和会话bean
    EJB初探
    JSF初探
    简单计算器
    关于坐火车
  • 原文地址:https://www.cnblogs.com/skylee03/p/7519749.html
Copyright © 2011-2022 走看看