【扩展KMP】POJ_3450| HDU_2328 Corporate Identity
2014-07-25 17:19
295 查看
原题直通车:POJ_3450 Corporate Identity HDU_2328
Corporate Identity
题意概述:找出N个串中最长公共子串
分析:
一、可以直接枚举其中一个串的所有字串,跟所有串进行匹配找到结果。
二、用其中一个串的每一个后缀和其它所有串分别求一次扩展KMP,并找到后缀中能在所有串中匹配到的最长前缀,最后在每个后缀的最长前缀中找出最长且字典序最小的。
代码参考:
KMP:
扩展KMP:
Corporate Identity
题意概述:找出N个串中最长公共子串
分析:
一、可以直接枚举其中一个串的所有字串,跟所有串进行匹配找到结果。
二、用其中一个串的每一个后缀和其它所有串分别求一次扩展KMP,并找到后缀中能在所有串中匹配到的最长前缀,最后在每个后缀的最长前缀中找出最长且字典序最小的。
代码参考:
KMP:
#include<iostream> #include<cstring> #include<string> #include<cstdio> using namespace std; const int maxn=4444; char x[222],ans[222], f[maxn][222]; int next[222], n; void strcpy(char *y,int i,int len){ for(int j=0;j<len;++i,++j) x[j]=y[i]; x[len]='\0'; } void Get_Next(char *s){ int len=strlen(s), i = 0, j = -1; next[0]=-1; while(i<len){ if(j==-1||s[i]==s[j]){ if(s[++i]==s[++j]) next[i]=next[j]; else next[i]=j; } else j=next[j]; } } bool KMP(char *s,char *a){ int ls=strlen(s), la=strlen(a); Get_Next(a); int i=0, j=0; while(i<ls&&j<la){ if(j==-1||s[i]==a[j]) ++i,++j; else j=next[j]; } if(j==la) return true; return false; } int main(){ while(~scanf("%d",&n),n){ for(int i=0; i<n; ++i) scanf("%s",f[i]); int len = strlen(f[0]); bool flag = false; ans[0]='\0'; for(int i=len; i && !flag; --i) for(int j=0,k; j<=len-i; ++j) { strcpy(f[0], j, i); for(k=1; k<n; ++k) if( !KMP(f[k],x) ) break; if(k==n && (!flag || strcmp(ans,x)>0)) { strcpy(ans, x); flag=true; } } if(flag) puts(ans); else puts("IDENTITY LOST"); } return 0; }
扩展KMP:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; char s[4005][205], f[4005][205], ans[205]; int next[205], extend[205]; void get_next(char *g) { int lg = strlen(g), j = 0; next[0] = lg; while(j+1<lg && g[j] == g[j+1]) ++j; next[1] = j; for(int i=2, k=1; i<lg; ++i) { int p = k+next[k]-1; int l = next[i-k]; if(i+l < p+1) next[i] = l; else { j = (p-i+1>0 ? p-i+1 : 0); while(i+j<lg && g[j] == g[i+j]) ++j; next[i] = j; k = i; } } } int ExKMP(char *s, char *g) { int ls = strlen(s), lg = strlen(g), j = 0, max_len; while(j<lg && j<ls && s[j] == g[j]) ++j; max_len = extend[0] = j; for(int i=1, k=0; i<ls; ++i) { int p = k+extend[k]-1; int l = next[i-k]; if(i+l < p+1) extend[i] = l; else { j = (p-i+1>0 ? p-i+1 : 0); while(i+j<ls && j<lg && s[i+j] == g[j]) ++j; extend[i] = j; k = i; } if(extend[i] > max_len) max_len = extend[i]; } return max_len; } int main() { int n; while(~scanf("%d", &n) && n) { for(int i=0; i<n; ++i) scanf("%s", s[i]); int len = strlen(s[0]), max_len = -1; for(int i=0; i<len; ++i) { get_next(s[0]+i); int mx = -1; for(int j=1; j<n; ++j) { int ml = ExKMP(s[j], s[0]+i); if(mx == -1 || ml < mx) mx = ml; } if(mx > max_len || (mx == max_len&&strncmp(ans, s[0]+i, mx)>0)) { strncpy(ans, s[0]+i, mx); max_len = mx; ans[mx] = '\0'; } } if(max_len>0) puts(ans); else puts("IDENTITY LOST"); } return 0; }
相关文章推荐
- POJ 1961 HDU 1358 KMP的性质
- hdu 4300 Clairewd’s message (扩展KMP)
- HDU 4333 Revolving Digits2012多校联赛第四场C题(扩展KMP+KMP)
- HDU 4749 && POJ 3167 KMP
- hdu 4333(扩展kmp)
- hdu 3068 最长回文 扩展KMP
- poj 3376 Finding Palindromes(扩展kmp+trie)
- HDU 3608 最长回文(扩展KMP)
- hdu4333之扩展KMP
- poj 1226|| hdu 1238 Substrings(KMP)
- hdu 4300 Clairewd’s message 扩展kmp
- HDU 4333 Revolving Digits (扩展KMP)
- hdu - 4333 - Revolving Digits - 扩展kmp
- KMP入门题 Hdu 1711 2594 3746 HUST 1010 Poj 3461 2752 2406 1961 FZU 1901
- hdu 4300 Clairewd’s message(扩展KMP)
- POJ 3461 HDU 1686 赤果果的KMP
- hdu 3068 最长回文 (Manacher O(n) ) (扩展KMP和后缀数组也都可以做 O(nlogn))
- hdu 3068(扩展KMP)
- hdu 4333 扩展kmp
- HDU 4333 Revolving Digits (扩展KMP)