题意:
求多个串的最长公共子串
这里用的是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 3 #include 4 #include 5 #include 6 #include 7 #include 8 #include <string> 9 #include 10 #include 11 #include 12 #include 13 #include 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" = "< 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 }