POJ2774 Long Long Message

POJ2774 Long Long Message

两串求最长公共子串

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 const int maxn = 2e5+5;
 7 char s[maxn];
 8 int sa[maxn], t[maxn], t2[maxn], c[maxn];
 9 int n;
10 //构造字符串s的后缀数组, 每个字符值必须为0 ~ m-1
11 void build_sa(int m) {
12     int *x = t, *y = t2;
13     //基数排序
14     for(int i = 0; i < m; i++) c[i] = 0;
15     for(int i = 0; i < n; i++) c[x[i] = s[i]]++;
16     for(int i = 1; i < m; i++) c[i] += c[i-1];
17     for(int i = n-1; i >= 0; i--) sa[--c[x[i]]] = i;
18     for(int k = 1; k <= n; k <<= 1) {
19         int p = 0;
20         //直接利用sa数组排序第二关键字
21         for(int i = n-k; i < n; i++) y[p++] = i;
22         for(int i = 0; i < n; i++) if(sa[i] >= k) y[p++] = sa[i] - k;
23         //基数排序第一关键字
24         for(int i = 0; i < m; i++) c[i] = 0;
25         for(int i = 0; i < n; i++) c[x[y[i]]]++;
26         for(int i = 1; i < m; i++) c[i] += c[i-1];
27         for(int i = n-1; i>= 0; i--) sa[--c[x[y[i]]]] = y[i];
28         //根据sa和y数组计算新的x数组
29         swap(x, y);
30         p = 1;
31         x[sa[0]] = 0;
32         for(int i = 1; i < n; i++)
33             x[sa[i]] = (y[sa[i-1]] == y[sa[i]] && y[sa[i-1]+k] == y[sa[i]+k] ? p-1 : p++);
34         if(p >= n) break;
35         m = p;
36     }
37 }
38 
39 int rank_[maxn]; //rank[i]代表后缀i在sa数组中的下标
40 int height[maxn]; //height[i] 定义为sa[i-1] 和 sa[i] 的最长公共前缀
41 //后缀j和k的LCP长度等于RMQ(height, rank[j]+1, rank[k])
42 void get_height() {
43     int i, j, k = 0;
44     for(int i = 0; i < n; i++) rank_[sa[i]] = i;
45     for(int i = 0; i < n; i++) {
46         if(!rank_[i]) continue;
47         int j = sa[rank_[i]-1];
48         if(k) k--;
49 
50         while(s[i+k] == s[j+k]) k++;
51         height[rank_[i]] = k;
52     }
53 }
54 
55 char s1[maxn], s2[maxn];
56 int main() {
57     scanf("%s %s",s1,s2);
58     int len1 = strlen(s1);
59     int len2 = strlen(s2);
60     
61     int cnt = 0;
62     for (int i = 0; i < len1; i++)
63         s[cnt++] = s1[i];
64     s[cnt++] = 1;
65     for (int i = 0; i < len2; i++)
66         s[cnt++] = s2[i];
67     s[cnt] = '\0';
68     n = strlen(s) + 1;
69     build_sa(128);
70     get_height();
71 
72     int ans = 0;
73     int be;
74     for (int i = 2; i < cnt; i++) {
75         if (sa[i-1] < len1 && sa[i] > len1) {
76             if (ans < height[i]) {
77                 be = sa[i-1];
78                 ans = height[i];
79             }
80         }
81         else if (sa[i-1] > len1 && sa[i] < len1) {
82             if (ans < height[i]) {
83                 be = sa[i];
84                 ans = height[i];
85             }
86         }
87     }
88     printf("%d\n",ans);
89     /*
90     printf("pos: %d\n", be);
91     for (int i = 0; i < ans; i++)
92         putchar(s[be+i]);
93     putchar('\n');
94     */
95     return 0;
96 }

 

posted @ 2019-10-25 20:53  麻辣猪仔  阅读(156)  评论(0编辑  收藏  举报