今天面試被一道沒見過的題,徹底整悶了。求一段字符串的最長重複子串。後來網上看看博客,居然能夠用KMP寫,爲本身的無知感到羞愧。好吧,我來學習一下如何用KMP方法解決這樣的問題,關鍵是next的特性來解決這個問題。ios
#include <iostream> #include <cstring> using namespace std; int Get_next(char *p, int nextval[]) { int j = -1; nextval[0] = -1; int len = strlen(p); int i = 0; int maxlen = 0; while(i < len) { if(j == -1 || p[i] == p[j]) { i++; j++; nextval[i] = j; if(j > maxlen) //求其中重複最大的字符串的個數,也就是與前面最前串的重複數 maxlen = j; } else j = nextval[j]; } return maxlen; } int main() { char s[100]; cin >> s; int maxlen = 0;//最大串的個數 int nextMax; //Get_next函數獲得的最大值 int i; int maxIndex; int len = strlen(s); for(i = 0; i < len-1; i++) { int *next = new int[len - i]; nextMax = Get_next(s + i, next); if(nextMax > maxlen) { maxIndex = i; maxlen = nextMax; } } cout << "輸出最長重複子串:" << endl; for(i = 0; i < maxlen; i++) cout << s[i + maxIndex]; cout << endl; }
使用KMP的特性來解決這道題,時間複雜度有點高啊。面試
事情總有解決的方法,因此就有了後綴數組這一數據結構來解決這個方法。對一個字符串生成相應的後綴數組後,再排序,排序後依次檢測相鄰的兩個字符串的開頭部分。數組
#include <iostream> #include <cstring> #include <stdio.h> #include <algorithm> using namespace std; #define MAXLEN 10000 char str[MAXLEN], *arr[MAXLEN]; int CalLen(const char *str1, const char *str2) { int len = 0; while(*str1 && (*str1++ == *str2++)) len++; return len; } int pStrCmp(const void *str1, const void *str2) { return strcmp(*(const char **)str1, *(const char **)str2); } int main() { char ch; int n = 0; int maxlen = 0, maxIndex = 0; int temp; while((ch = getchar()) != '\n') { arr[n] = &str[n]; str[n++] = ch; } str[n] = '\0'; qsort(arr, n, sizeof(char *), pStrCmp); for(int i = 0; i < n - 1; i++) { temp = CalLen(arr[i], arr[i + 1]); if(temp > maxlen) { maxlen = temp; maxIndex = i; } } cout << arr[maxIndex] << endl;; }