多个串的最长公共子串 SPOJ - LCS2 后缀自动机

∥☆過路亽.° 提交于 2019-11-30 02:01:31

题意:

求多个串的最长公共子串

这里用的是O(n)的后缀自动机写法

我后缀数组的专题有nlog(n)写法的

 

题解:

对于其中的一个串建立后缀自动机

然后对于后缀自动机上面的每一个节点求出每一个节点最长可以匹配的子串(用maxx【】数组存下)

但是在后缀自动机上面有些节点没有走过,但是是某些走过的点的父亲节点因此也是有值的

for (int i = tot; i; i--)    maxx[fail[i]] = max(maxx[fail[i]], min(len[fail[i]], maxx[i]));然后求一个所有最小值里面的最大值就好了
  1 #include <set>
  2 #include <map>
  3 #include <stack>
  4 #include <queue>
  5 #include <cmath>
  6 #include <ctime>
  7 #include <cstdio>
  8 #include <string>
  9 #include <vector>
 10 #include <cstring>
 11 #include <iostream>
 12 #include <algorithm>
 13 #include <unordered_map>
 14 
 15 #define  pi    acos(-1.0)
 16 #define  eps   1e-9
 17 #define  fi    first
 18 #define  se    second
 19 #define  rtl   rt<<1
 20 #define  rtr   rt<<1|1
 21 #define  bug                printf("******\n")
 22 #define  mem(a, b)          memset(a,b,sizeof(a))
 23 #define  name2str(x)        #x
 24 #define  fuck(x)            cout<<#x" = "<<x<<endl
 25 #define  sfi(a)             scanf("%d", &a)
 26 #define  sffi(a, b)         scanf("%d %d", &a, &b)
 27 #define  sfffi(a, b, c)     scanf("%d %d %d", &a, &b, &c)
 28 #define  sffffi(a, b, c, d) scanf("%d %d %d %d", &a, &b, &c, &d)
 29 #define  sfL(a)             scanf("%lld", &a)
 30 #define  sffL(a, b)         scanf("%lld %lld", &a, &b)
 31 #define  sfffL(a, b, c)     scanf("%lld %lld %lld", &a, &b, &c)
 32 #define  sffffL(a, b, c, d) scanf("%lld %lld %lld %lld", &a, &b, &c, &d)
 33 #define  sfs(a)             scanf("%s", a)
 34 #define  sffs(a, b)         scanf("%s %s", a, b)
 35 #define  sfffs(a, b, c)     scanf("%s %s %s", a, b, c)
 36 #define  sffffs(a, b, c, d) scanf("%s %s %s %s", a, b,c, d)
 37 #define  FIN                freopen("../in.txt","r",stdin)
 38 #define  gcd(a, b)          __gcd(a,b)
 39 #define  lowbit(x)          x&-x
 40 #define  IO                 iOS::sync_with_stdio(false)
 41 
 42 
 43 using namespace std;
 44 typedef long long LL;
 45 typedef unsigned long long ULL;
 46 const ULL seed = 13331;
 47 const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;
 48 const int maxn = 1e6 + 50;
 49 const int maxm = 8e6 + 10;
 50 const int INF = 0x3f3f3f3f;
 51 const int mod = 1e9 + 7;
 52 char s[maxn];
 53 
 54 struct Suffix_Automaton {
 55     int last, tot, nxt[maxn << 1][26], fail[maxn << 1];//last是未加入此字符前最长的前缀(整个串)所属的节点的编号
 56     int len[maxn << 1];// 最长子串的长度 (该节点子串数量 = len[x] - len[fail[x]])
 57     int maxx[maxn << 1];
 58 
 59     void init() {
 60         tot = last = 1;
 61         fail[1] = len[1] = 0;
 62         for (int i = 0; i < 26; i++) nxt[1][i] = 0;
 63     }
 64 
 65     void extend(int c) {
 66         int u = ++tot, v = last;
 67         for (int i = 0; i < 26; i++) nxt[u][i] = 0;
 68         fail[u] = 0;
 69         len[u] = len[v] + 1;
 70         for (; v && !nxt[v][c]; v = fail[v]) nxt[v][c] = u;
 71         if (!v) fail[u] = 1;
 72         else if (len[nxt[v][c]] == len[v] + 1) fail[u] = nxt[v][c];
 73         else {
 74             int now = ++tot, cur = nxt[v][c];
 75             len[now] = len[v] + 1;
 76             memcpy(nxt[now], nxt[cur], sizeof(nxt[cur]));
 77             fail[now] = fail[cur];
 78             fail[cur] = fail[u] = now;
 79             for (; v && nxt[v][c] == cur; v = fail[v]) nxt[v][c] = now;
 80         }
 81         last = u;
 82         //return len[last] - len[fail[last]];//添加一个新的字符产生的新的本质不同的子串数目
 83     }
 84 
 85     int minn[maxn << 1];
 86 
 87     void match() {
 88         mem(maxx, 0);
 89         int n = strlen(s);
 90         int p = 1, maxlen = 0;
 91         for (int i = 0; i < n; i++) {
 92             int c = s[i] - 'a';
 93             if (nxt[p][c]) p = nxt[p][c], maxlen++;
 94             else {
 95                 for (; p && !nxt[p][c]; p = fail[p]);
 96                 if (!p) p = 1, maxlen = 0;
 97                 else maxlen = len[p] + 1, p = nxt[p][c];
 98             }
 99             maxx[p] = max(maxx[p], maxlen);
100         }
101         for (int i = tot; i; i--)
102             maxx[fail[i]] = max(maxx[fail[i]], min(len[fail[i]], maxx[i]));
103         for (int i = tot; i; i--)
104             if (minn[i] == -1 || minn[i] > maxx[i]) minn[i] = maxx[i];
105     }
106 
107 } sam;
108 
109 
110 int main() {
111 #ifndef ONLINE_JUDGE
112     FIN;
113 #endif
114     sfs(s);
115     int n = strlen(s);
116     sam.init();
117     for (int i = 0; i < n; ++i) sam.extend((s[i] - 'a'));
118     for (int i = 0; i <= sam.tot; i++) sam.minn[i] = -1;
119     while (~sfs(s)) sam.match();
120     int ans = 0;
121     for (int i = 1; i <= sam.tot; i++) ans = max(ans, sam.minn[i]);
122     printf("%d\n", ans);
123 #ifndef ONLINE_JUDGE
124     cout << "Totle Time : " << (double) clock() / CLOCKS_PER_SEC << "s" << endl;
125 #endif
126     return 0;
127 }
View Code

 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!