这里串最多有10个,找所有串的最长公共子串
这里后缀自动机做,以第一个串建立后缀自动机,后面的串一个个去匹配,每次得到当前串在可到达状态上所能得到的最长后缀长度
拿所有串匹配后得到的结果进行计算
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 #define M 26 6 #define N 200100 7 char str[N]; 8 struct SamNode{ 9 SamNode *son[M] , *f; 10 int l , nc , c; 11 }sam[N] , *last , *root , *b[N]; 12 13 int cnt , num[N]; 14 15 void init() 16 { 17 root = last = &sam[cnt=0]; 18 } 19 20 void add(int x) 21 { 22 SamNode *p = &sam[++cnt] , *jp=last; 23 p->l = jp->l+1 , p->nc = p->l; 24 last = p; 25 for( ; jp&&!jp->son[x] ; jp=jp->f) jp->son[x]=p; 26 if(!jp) p->f = root; 27 else{ 28 if(jp->l+1 == jp->son[x]->l) p->f = jp->son[x]; 29 else{ 30 SamNode *r = &sam[++cnt] , *q = jp->son[x]; 31 *r = *q; 32 r->l = r->nc = jp->l+1; 33 q->f = p->f = r; 34 for( ; jp && jp->son[x]==q ; jp=jp->f) jp->son[x]=r; 35 } 36 } 37 } 38 39 void solve() 40 { 41 int len = strlen(str) , ret; 42 for(int i=0 ; i<=cnt ; i++) num[sam[i].l]++; 43 for(int i=1 ; i<=len ; i++) num[i]+=num[i-1]; 44 for(int i=0 ; i<=cnt ; i++) b[--num[sam[i].l]] = &sam[i]; 45 while(~scanf("%s" , str)){ 46 len = strlen(str) , ret=0; 47 SamNode *cur = root; 48 for(int i=0 ; i<len ; i++){ 49 int x = str[i]-'a'; 50 if(cur->son[x]){ 51 ret++; 52 cur = cur->son[x]; 53 } 54 else{ 55 while(cur && !cur->son[x]) cur = cur->f; 56 if(!cur){ 57 cur = root; 58 ret = 0; 59 }else{ 60 ret = cur->l+1; 61 cur = cur->son[x]; 62 } 63 } 64 cur->c = max(cur->c , ret); 65 } 66 for(int i=cnt ; i>0 ; i--){ 67 b[i]->nc = min(b[i]->nc , b[i]->c); 68 //子节点可接受到的后缀父节点必定能够接收到,反之却不一定 69 b[i]->f->c = max(b[i]->f->c , b[i]->c); 70 b[i]->c = 0; 71 } 72 } 73 } 74 75 int main() { 76 // freopen("a.in" , "r" , stdin); 77 scanf("%s" , str); 78 init(); 79 int len = (int)strlen(str); 80 for(int i=0 ; i<len ; i++) add(str[i]-'a'); 81 solve(); 82 int ret = 0; 83 SamNode *cur; 84 for(int i=1 ; i<=cnt ; i++){ 85 cur = &sam[i]; 86 ret = max(cur->nc , ret); 87 } 88 printf("%d " , ret); 89 return 0; 90 }