POJ2774 Long Long Message
题目链接:http://poj.org/problem?id=2774
The little cat is majoring in physics in the capital of Byterland. A piece of sad news comes to him these days: his mother is getting ill. Being worried about spending so much on railway tickets (Byterland is such a big country, and he has to spend 16 shours on train to his hometown), he decided only to send SMS with his mother...
题目大意:给两个字符串,求出该两个字符串中公共子串的最大长度。
思路:
1.其实我认为可以枚举第一个字符串的各个子串,然后用kmp求得公共子串的最大长度的。但好像没人这么写,是哪儿有问题吗? 如果有有缘人看到了并且知道为什么 ,欢迎加我QQ:709401953 ,帮我解答 请你吃饭饭。
2.用一个不会出现的字符连接两个字符串,对连接后的字符串跑一遍height数组,height数组的含义是字典序排名为 i 与排名为 i - 1的后缀的最长公共前缀的长度。
跑height数组模板:
1 void get_H() 2 { 3 int k = 0; 4 for(int i = 1; i <= len; i ++) 5 rank[sa[i]] = i; 6 for(int i = 1; i <= len; i ++) 7 { 8 if(k) 9 k --; 10 int j = sa[rank[i] - 1]; 11 while(s[i + k] == s[j + k]) 12 k ++; 13 height[rank[i]] = k; 14 } 15 }
AC代码:
1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 #define mem(a, b) memset(a, b, sizeof(a)) 5 const int MAXN = 1e5 + 10; 6 using namespace std; 7 8 char s1[MAXN], s2[MAXN], s[2 * MAXN]; 9 int len, size; 10 int rank[2 * MAXN], sa[2 * MAXN], tax[2 * MAXN], tp[2 * MAXN], height[2 * MAXN], p; 11 12 void Q_sort() 13 { 14 for(int i = 0; i <= size; i ++) tax[i] = 0; 15 for(int i = 1; i <= len; i ++) tax[rank[i]] ++; 16 for(int i = 1; i <= size; i ++) tax[i] += tax[i - 1]; 17 for(int i = len; i >= 1; i --) sa[tax[rank[tp[i]]] --] = tp[i]; 18 } 19 20 void get_H() 21 { 22 int k = 0; 23 for(int i = 1; i <= len; i ++) 24 rank[sa[i]] = i; 25 for(int i = 1; i <= len; i ++) 26 { 27 if(k) 28 k --; 29 int j = sa[rank[i] - 1]; 30 while(s[i + k] == s[j + k]) 31 k ++; 32 height[rank[i]] = k; 33 } 34 } 35 36 void get_SA() 37 { 38 for(int i = 1; i <= len; i ++) rank[i] = s[i], tp[i] = i; 39 Q_sort(); 40 for(int w = 1; w <= len; w *= 2) 41 { 42 p = 0; 43 for(int i = 1; i <= w; i ++) tp[++ p] = len - w + i; 44 for(int i = 1; i <= len; i ++) if(sa[i] > w) tp[++ p] = sa[i] - w; 45 Q_sort(); 46 swap(tp, rank);//tp数组无用 继承上一轮rank排名 47 rank[sa[1]] = p = 1; 48 for(int i = 2; i <= len; i ++) 49 rank[sa[i]] = (tp[sa[i - 1]] == tp[sa[i]] && tp[sa[i - 1] + w] == tp[sa[i] + w]) ? p : ++ p; 50 size = p; 51 if(p >= len) 52 break; 53 } 54 get_H(); 55 } 56 57 int main() 58 { 59 scanf("%s%s", s1 + 1, s2 + 1); 60 int len1 = strlen(s1 + 1), len2 = strlen(s2 + 1); 61 int cnt = 0; 62 for(int i = 1; i <= len1; i ++) 63 s[++ cnt] = s1[i]; 64 s[++ cnt] = '#'; //用一个不会出现的字符连接两个字符串。 65 for(int i = 1; i <= len2; i ++) 66 s[++ cnt] = s2[i]; 67 len = strlen(s + 1), size = 130; 68 get_SA(); 69 int ans = 0; 70 for(int i = 2; i <=len; i ++) 71 { 72 if(sa[i - 1] <= len1 && sa[i] > len1 + 1) 73 ans = max(ans, height[i]); 74 else if(sa[i - 1] > len1 + 1 && sa[i] <= len1) 75 ans = max(ans, height[i]); 76 } 77 printf("%d\n", ans); 78 return 0; 79 }