kuangbin专题16I(kmp)
题目链接: https://vjudge.net/contest/70325#problem/I
题意: 求多个字符串的最长公共子串, 有多个则输出字典序最小的.
思路: 这里的字符串长度固定为 60, 可以枚举其中一个字符串的所有子串, 然后拿这个子串去和其他字符串匹配就好了. 不过如果不用 kmp 的话需要 O(N^5) 的时间复杂度, 因该会 tle.
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 using namespace std; 5 6 const int MAXN = 1e2; 7 int len, nxt[MAXN]; 8 char s[MAXN], sol[MAXN], str[12][MAXN]; 9 10 void get_nxt(void){ 11 memset(nxt, 0, sizeof(nxt)); 12 for(int i = 1; i < len; i++){ 13 int j = nxt[i]; 14 while(j && s[i] != s[j]){ 15 j = nxt[j]; 16 } 17 nxt[i + 1] = j + (s[i] == s[j]); 18 } 19 } 20 21 bool kmp(char *gel){ 22 for(int i = 0, j = 0; i < strlen(gel); i++){ 23 while(j && gel[i] != s[j]){ 24 j = nxt[j]; 25 } 26 if(gel[i] == s[j]) j++; 27 if(j >= len) return true; 28 } 29 return false; 30 } 31 32 int main(void){ 33 int t, n; 34 scanf("%d", &t); 35 while(t--){ 36 int cnt = 0; 37 scanf("%d", &n); 38 for(int i = 0; i < n; i++){ 39 scanf("%s", str[i]); 40 } 41 for(int i = 0; i < 58; i++){ 42 len = 0; 43 bool flag = true; 44 s[len++] = str[0][i]; 45 s[len++] = str[0][i + 1]; 46 for(int j = i + 2; j < 60; j++){ 47 s[len++] = str[0][j]; 48 s[len] = '\0'; 49 get_nxt(); 50 for(int k = 1; k < n; k++){ 51 flag = kmp(str[k]); 52 if(!flag) break; 53 } 54 if(!flag) break; 55 else{ 56 if(j - i + 1 > cnt){ 57 cnt = j - i + 1; 58 strcpy(sol, s); 59 }else if(j - i + 1 == cnt){ 60 if(strcmp(sol, s) > 0) strcpy(sol, s); 61 } 62 } 63 } 64 } 65 if(cnt < 3) puts("no significant commonalities"); 66 else printf("%s\n", sol); 67 } 68 return 0; 69 }
我就是我,颜色不一样的烟火 --- geloutingyu