就是求两个字符串的最长公共字符串,使用后缀数组,空间复杂度O(nlogn),花了2天时间来搞懂后缀数组,但是测试了很多数据没有发现什么错误,不知为什么这题在G++是RE,在C++下是WA,先贴代码,日后再分析。注意两个字符串之间要加分隔符 #include <iostream> #include <cstdio> #include <cstring> using namespace std; #define maxasc 128 #define maxn 200002 int sum[maxasc+1]; int Rank[maxn], trank[maxn]; int sa[maxn], tsa[maxn]; int height[maxn]; char s[maxn]; int len; void radixsort(int j) { memset(sum, 0, sizeof(sum)); for (int i = 0; i < len; ++i) ++sum[ Rank[i+j] ]; for (int i = 1; i <= maxasc; ++i) sum[i] += sum[i-1]; for (int i = len-1; i >= 0; --i) tsa[ --sum[ Rank[i+j] ] ] = i; //对第二关键字基数排序 memset(sum, 0, sizeof(sum)); for (int i = 0; i < len; ++i) ++sum[ Rank[i] ]; for (int i = 1; i <= maxasc; ++i) sum[i] += sum[i-1]; for (int i = len-1; i >= 0; --i) sa[ --sum[ Rank[ tsa[i] ] ] ] = tsa[i]; //对第一关键字基数排序 } void get_sa() { int p; for (int i = 0; i < len; ++i) trank[i] = s[i]; for (int i = 0; i < len; ++i) ++sum[ trank[i] ]; for (int i = 1; i <= maxasc; ++i) sum[i] += sum[i-1]; for (int i = len-1; i >= 0; --i) sa[ --sum[ trank[i] ] ] = i; Rank[ sa[0] ] = 0; for (int i=1, p=0; i < len; ++i) { if (trank[ sa[i] ] != trank[ sa[i-1] ]) ++p; Rank[ sa[i] ] = p; } // 第一次sa与Rank构造完成 for (int j = 1; j <= len; j*=2) { //每次比较增长长度 radixsort(j); trank[ sa[0] ] = 0; p = 0; for (int i = 1; i < len; ++i) { if ( (Rank[ sa[i] ] != Rank[ sa[i-1] ]) || (Rank[ sa[i]+j ] != Rank[ sa[i-1]+j ]) ) ++p; trank[ sa[i] ] = p; } for (int i = 0; i < len; ++i) Rank[i] = trank[i]; } } void get_height() { for (int i=0,j=0; i < len; ++i) { if (Rank[i] == 0) continue; while (s[i+j] == s[ sa[ Rank[i]-1 ]+j ]) ++j; height[ Rank[i] ] = j; if (j > 0) --j; } } int main() { freopen("temp.txt", "r", stdin); int len1, max_len=0; scanf("%s", s); len1 = strlen(s); s[len1] = '|'; //非常关键的分隔符 scanf("%s", s+len1+1); len = strlen(s) + 1; get_sa(); get_height(); for (int i = 1; i < len; ++i) { if ( ((sa[i] < len1 && sa[i-1] > len1) || (sa[i-1] < len1 && sa[i] > len1)) && height[i] > max_len ) {// 在不同字符串 max_len = height[i]; } } cout << max_len << endl; return 0; }