具体的解题思路可以参考下面罗列的网址。
- /*
- Title: Long Long Message
- Author: Jeff
- Time: 2008/10/21
- Complexity: O(N*log(N));
- Result: 5944K 1094MS/ AC
- Reference:
- http://imlazy.ycool.com/post.2011818.html
- http://imlazy.ycool.com/post.2011825.html
- http://chencb.ycool.com/post.1901840.html
- http://203.208.39.99/search?q=cache:zQ9R83uI7hoJ:jgshining.cn/blog/post/suffix_array_implemention.php+%E6%9C%80%E9%95%BF%E5%85%AC%E5%85%B1%E5%89%8D%E7%BC%80&hl=zh-CN&newwindow=1&gl=cn&st_usg=ALhdy2_b5qju9mjFwiOWprnZP-4EhzPliw&strip=1
- Description:
- 求两个串的最长公共子串
- Tips:
- LCP问题,后缀数组。
- p.s.
- */
- #include <cstdio>
- #include <cstring>
- #include <algorithm>
- using namespace std;
- const int MAX = 100000;
- struct Sfx{
- int idx; //保存原始的下标
- int key[2]; //双关键字,k前缀意义下和2k前缀意义下
- bool operator<(const Sfx &other)const{ //用于排序
- return (key[0] < other.key[0]) ||
- (key[0] == other.key[0] && key[1] < other.key[1]);
- }
- };
- Sfx tempSfx[2][MAX * 2 + 2]; //[0]用于存放SA结果,[1]用于中间变量
- int buf[MAX * 2 + 2]; //用于存放rank[];
- char strText[MAX * 2 + 2]; //原始字符串
- int H[MAX * 2 + 2]; //H数组
- int ans;
- //计数排序 O(n)
- void cSort(Sfx *in, int len, int key, Sfx *out){
- memset(H, 0, sizeof(H));
- int *cnt = H;
- for(int i = 0; i < len; i++)
- cnt[ in[i].key[key] ]++;
- for(int i = 1; i < len; i++)
- cnt[i] += cnt[i - 1];
- for(int i = len - 1; i >= 0; i--)
- out[ --cnt[in[i].key[key]] ] = in[i];
- }
- void buildSaf(char *text, int len){
- Sfx *pTmp = tempSfx[1], *pSA = tempSfx[0];
- int *rank = buf;
- //初始化
- for(int i = 0; i < len; i++){
- pSA[i].idx = pSA[i].key[1] = i;
- pSA[i].key[0] = text[i];
- }
- sort(pSA, pSA + len);
- for(int i = 0; i < len; i++)pSA[i].key[1] = 0;
- //log(n)次操作
- int wid = 1;
- while(wid < len){
- //计算rank值
- rank[pSA[0].idx] = 0;
- for(int i = 1; i < len; i++){
- rank[pSA[i].idx] = rank[pSA[i-1].idx];
- if(pSA[i-1] < pSA[i])
- rank[pSA[i].idx]++;
- }
- //赋值关键字
- for(int i = 0; i < len; i++){
- pSA[i].idx = i;
- pSA[i].key[0] = rank[i];
- pSA[i].key[1] = (i + wid < len ? rank[i+wid] : 0);
- }
- cSort(pSA, len, 1, pTmp); cSort(pTmp, len, 0, pSA); //对双关键字进行计数排序
- wid *= 2;
- }
- }
- //计算H数组
- void calculateH(char *text, int len1, int len2){
- int *rank = buf;
- Sfx *pSA = tempSfx[0];
- for(int i = 0; i < len1 + len2; i++){
- if(rank[i] == 0)
- H[i] = 0;
- else{
- int k, j;
- if(i == 0 || H[i - 1] < 1){
- k = 0;
- }else{
- k = H[i-1] - 1;
- }
- for(j = pSA[ rank[i]-1 ].idx; text[j + k] == text[i + k]; k++);
- H[i] = k;
- //求出结果
- if(i < len1 && j >= len1 || i >= len1 && j < len1)
- if(ans < H[i])
- ans = H[i];
- }
- }
- }
- int main(){
- freopen("in.txt", "r", stdin);
- freopen("out.txt", "w", stdout);
- while(scanf("%s", strText) != EOF){
- ans = 0;
- int len1 = strlen(strText);
- scanf("%s", strText + len1);
- int len2 = strlen(strText) - len1;
- buildSaf(strText, len1 + len2);
- calculateH(strText, len1, len2);
- Sfx *pSA = tempSfx[0];
- /*for(int i = 0; i < len1 + len2; i++)
- printf("%d ", pSA[i].idx);
- printf("/n");
- for(int i = 0; i < len1 + len2; i++)
- printf("%d ", buf[i]);
- printf("/n");
- for(int i = 0; i < len1 + len2; i++)
- printf("%d ", H[i]);
- printf("/n");*/
- printf("%d/n", ans);
- }
- return 0;
- }