• SPOJ LCS2


    LCS2 - Longest Common Substring II

    链接

    题意:

      求N(N<=10)个串的最长公共子串。

    分析:

      poj2774上那道题,对一个串建立后缀自动机,另一个在上面匹配。

      这道题是对多个串求。那么同样,让每个串在后缀自动机上匹配,然后记录在后缀自动机的每个节点上记录,当前串在这个位置和第一个串的最大匹配数,h数组。

      然后mn数组,每次对于这所有的节点的h取小,为从第2个串到现在所有的串,都能在这个节点上匹配的长度。

      因为一旦某个节点匹配上了,那么它的父节点(parent树)的父节点都会匹配上(因为父节点是当前点的后缀),所以按拓扑倒序,更新父节点的h,为父节点的len,(即最大长度)。

      第二种写法是对n-1个字符串建立SAM,然后用最后一个串在n-1个串上匹配,每个自动机上都有一个当前的指针cur,当前答案ans。对最后一个串从头开始扫,求出最后一个串和每个串以当前字符结尾的最大匹配长度,在这里面取小,每次加入一个字符,可以直接判断cur的下一位,不需要从头开始。空间太大。

      

      两种写法大同小异,只枚举举的顺序不同而已。

    代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long LL;
     4 
     5 inline int read() {
     6     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
     7     for (;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
     8 }
     9 
    10 const int N = 100010;
    11 
    12 struct Suffix_Automaton{
    13     int fa[N<<1], trans[N<<1][26], len[N<<1], Last, Index;
    14     int v[N], sa[N<<1], mn[N<<1], h[N<<1];
    15     char s[N];
    16     
    17     void extend(int c) {
    18         int P = Last,NP = ++Index;
    19         len[NP] = len[P] + 1;
    20         for (; P&&!trans[P][c]; P=fa[P]) trans[P][c] = NP;
    21         if (!P) fa[NP] = 1; //-
    22         else {
    23             int Q = trans[P][c];
    24             if (len[P] + 1 == len[Q]) fa[NP] = Q;
    25             else {
    26                 int NQ = ++Index;
    27                 fa[NQ] = fa[Q];
    28                 len[NQ] = len[P] + 1;
    29                 memcpy(trans[NQ], trans[Q], sizeof trans[Q]);
    30                 fa[Q] = NQ;
    31                 fa[NP] = NQ;
    32                 for (; P&&trans[P][c]==Q; P=fa[P]) trans[P][c] = NQ;
    33             }
    34         }
    35         Last = NP;
    36     }
    37     void build() {
    38         Last = Index = 1;
    39         scanf("%s",s+1);
    40         int n = strlen(s+1);
    41         for (int i=1; i<=n; ++i) extend(s[i] - 'a');
    42         for (int i=1; i<=Index; ++i) v[len[i]] ++;
    43         for (int i=1; i<=n; ++i) v[i] += v[i-1];
    44         for (int i=1; i<=Index; ++i) sa[ v[len[i]]-- ] = i; // sa[i] 排名为i的节点。按深度排名(拓扑用) 
    45     }
    46     void calcc() {
    47         int n = strlen(s+1), now = 0, p = 1;
    48         memset(h, 0, sizeof(h));
    49         for (int i=1; i<=n; ++i) {
    50             int c = s[i] - 'a';
    51             if (trans[p][c]) p = trans[p][c], now ++;
    52             else {
    53                 for (; p&&!trans[p][c]; p=fa[p]);
    54                 if (!p) now = 0, p = 1;
    55                 else now = len[p] + 1, p = trans[p][c];
    56             }
    57             h[p] = max(h[p], now);
    58         }
    59         for (int i=Index; i>=1; --i) { // 拓扑倒序,parent树中从深度深的到浅的 
    60             int t = sa[i];
    61             mn[t] = min(mn[t], h[t]);
    62             if (h[t] && fa[t]) h[fa[t]] = len[fa[t]];
    63         }
    64     }
    65     void solve() {
    66         build();
    67         memset(mn, 0x3f, sizeof(mn));
    68         while (scanf("%s",s+1) != EOF) calcc();        
    69         int ans = 0;
    70         for (int i=1; i<=Index; ++i) ans = max(ans, mn[i]);
    71         printf("%d",ans);
    72     }
    73 }sam;
    74 
    75 int main() {
    76     sam.solve();
    77     return 0;
    78 }
    View Code
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long LL;
     4 
     5 inline int read() {
     6     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
     7     for (;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
     8 }
     9 
    10 const int N = 200010;
    11 
    12 struct SuffixAutomaton{
    13     int Last, Index, res, cur, fa[N], trans[N][26], len[N];
    14     SuffixAutomaton() {Last = Index = cur = 1; res = 0;}
    15     void extend(int c) {
    16         int P = Last, NP = ++Index;
    17         len[NP] = len[P] + 1;
    18         for (; P&&!trans[P][c]; P=fa[P]) trans[P][c] = NP;
    19         if (!P) fa[NP] = 1;
    20         else {
    21             int Q = trans[P][c];
    22             if (len[P] + 1 == len[Q]) fa[NP] = Q;
    23             else {
    24                 int NQ = ++Index;
    25                 fa[NQ] = fa[Q];
    26                 len[NQ] = len[P] + 1;
    27                 memcpy(trans[NQ], trans[Q], sizeof trans[Q]);
    28                 fa[Q] = NQ;
    29                 fa[NP] = NQ;
    30                 for (; P&&trans[P][c]==Q; P=fa[P]) trans[P][c] = NQ;
    31             }
    32         }
    33         Last = NP;
    34     }
    35     int solve(int c) {
    36         if (trans[cur][c]) {cur = trans[cur][c]; res++; return res;}
    37         for (; cur&&!trans[cur][c]; cur=fa[cur]);
    38         if (!cur) res = 0, cur = 1;
    39         else res = len[cur] + 1, cur = trans[cur][c];
    40         return res;
    41     }
    42 }sam[9];
    43 
    44 char s[N];
    45 char str[N];
    46 
    47 int main() {
    48     int n = 0,t = 0,len;
    49     scanf("%s",str+1);
    50     
    51     while (scanf("%s",s+1)!=EOF) {
    52         len = strlen(s + 1);
    53         for (int i=1; i<=len; ++i) 
    54             sam[t].extend(s[i] - 'a');
    55         t ++;
    56     }
    57     int ans = 0;
    58     len = strlen(str+1);
    59     for (int i=1; i<=len; ++i) {
    60         int tmp = 1e9;
    61         for (int j=0; j<t; ++j) 
    62             tmp = min(tmp, sam[j].solve(str[i] - 'a'));
    63         ans = max(ans, tmp);
    64     }
    65     printf("%d",ans);
    66     return 0;
    67 }
    View Code
  • 相关阅读:
    mysql innodb ini
    innodb_flush_method
    mysql查询缓存
    查看表的索引
    mysql key PRI UNI MUL
    E160028
    mysql命令
    No identifier specified for entity
    在画图板中添加文本并更改文本颜色
    在Windows资源管理器中预览PowerShell文件
  • 原文地址:https://www.cnblogs.com/mjtcn/p/9335863.html
Copyright © 2020-2023  润新知