HDU 1403 Longest Common Substring .

Longest Common Substring
Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 1453    Accepted Submission(s): 419



Problem Description
Given two strings, you have to tell the length of the Longest Common Substring of them.

For example:
str1 = banana
str2 = cianaic

So the Longest Common Substring is "ana", and the length is 3.





Input
The input contains several test cases. Each test case contains two strings, each string will have at most 100000 characters. All the characters are in lower-case.

Process to the end of file.





Output
For each test case, you have to tell the length of the Longest Common Substring of them.





Sample Input
banana cianaic




Sample Output
3 今次系第一次用倍增算法构建后缀数组,我写既呢个其实比较好理解,哈哈,因为我好老实甘对SA两个关键字排序鸟,无花巧野,好直接,不过自己写既效率真系不敢恭维,可能直接过头………………{=    =}3898619 2011-05-02 09:27:06 Accepted 1403 1015MS 8056K 2800 B G++ 10SGetEternal{(。)(。)}! 3898664 2011-05-02 09:45:07 Accepted 1403 968MS 8060K 2901 B G++ 10SGetEternal{(。)(。)}! 3898667 2011-05-02 09:45:32 Accepted 1403 843MS 6844K 2901 B G++ 10SGetEternal{(。)(。)}! 3898750 2011-05-02 10:09:18 Accepted 1403 828MS 6852K 3481 B G++ 10SGetEternal{(。)(。)}! 3898973 2011-05-02 11:06:51 Accepted 1403 750MS 6964K 2441 B G++ 10SGetEternal{(。)(。)}! 3900666 2011-05-02 20:02:15 Accepted 1403 734MS 6900K 2827 B C++ 10SGetEternal{(。)(。)}! 3900874 2011-05-02 20:42:53 Accepted 1403 484MS 6900K 2496 B C++ 10SGetEternal{(。)(。)}! 3900895 2011-05-02 20:45:23 Accepted 1403 468MS 6900K 2258 B C++ 10SGetEternal{(。)(。)}! 3900928 2011-05-02 20:49:18 Accepted 1403 93MS 6756K 2329 B C++ 10SGetEternal{(。)(。)}! 93ms!!!!!感动到内牛满面!!!!!!!!!!{=       =} 下面献上优化代码,终于可以做模版鸟可以。

 

睇住baidu后缀数组代码真系好鬼死蛋痛…………好难睇下。
关于我对后缀数组既理解会另外写系数据结构9up度,我会尽量用写得容易理解d,少d理论,多d图片,平凡d,造福人类。
 
#include<iostream.h>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<memory.h>
#define MAXI 200011

int l, key1[MAXI], key2[MAXI], rank[MAXI], tsa[MAXI], sa[MAXI], h[MAXI], heigth[MAXI],  hash[MAXI];
char buf[MAXI], tbuf[MAXI];
int *s1 = sa, *s2 = tsa;

void CS(int *key)
{
    int i, *t;
    memset(hash, 0, sizeof hash);
    for (i = 0; i < l; i++) hash[key[s1[i]]]++;
    for (i = 1; i < MAXI; i++) hash[i] += hash[i-1];
    for (i = l - 1; i >= 0; i--) s2[--hash[key[s1[i]]]] = s1[i];
    t = s1; s1 = s2; s2 = t;
}

void CSA(char *str)
{
    int i, j;
    
    for (i = 0; i < l; i++) s1[i] = i, key1[i] = str[i];
    CS(key1);
    for (rank[s1[0]] = 0, i = 1; i < l; i++)
        if (key1[s1[i]] == key1[s1[i - 1]]) rank[s1[i]] = rank[s1[i-1]];
        else rank[s1[i]] = rank[s1[i - 1]] + 1;

    for (j = 1; j < l; j *= 2)
    {
        for (i = 0; i < l; i++)
        {
            key1[i] = rank[i];
            if (i + j < l ) key2[i] = rank[i + j];
            else key2[i] = 0;
        }

        CS(key2);
        CS(key1);

        for (rank[s1[0]] = 0, i = 1; i < l; i++)
            if (key1[s1[i]] == key1[s1[i - 1]] && key2[s1[i]] == key2[s1[i - 1]]) 
                rank[s1[i]] = rank[s1[i-1]];
            else rank[s1[i]] = rank[s1[i - 1]] + 1;
    }
    if (s1 != sa) memcpy(sa, tsa, sizeof tsa);
}

void CHA(char *str)
{
    int i, j, k = 0;
    
    for (i = 0; i < l; heigth[rank[i++]] = k)
        for (k? k-- : 0, j = sa[rank[i] - 1]; str[i + k] == str[j + k]; k++);
}

void CHA1(char *str)
{
    int i, j, k, add;

    for (i = 0; i < l; i++)
    {
        if (rank[i] == 0)
        {
            h[i] = 0; 
            continue;
        }
        j = rank[i];
        k = rank[i] - 1;
        if (i == 0 || h[i - 1] <= 1) add = 0;
        else add = h[i - 1] - 1;
        while (str[sa[j] + add] == str[sa[k] + add]) add++;
        h[i] = add;
    }
    for (i = 0; i < l; i++) heigth[rank[i]] = h[i];
}

int main()
{
    int l1, l2, T, i, j, k, p, maxi;
    double sum, ave;

    while (scanf("%s", tbuf) != EOF)
    {
        l1 = strlen(tbuf);
        for (l = i = 0; i < l1; i++) buf[l++] = tbuf[i];
        buf[l++] = '#';
        scanf("%s", tbuf);
        l2 = strlen(tbuf);
        for (i = 0; i < l2; i++) buf[l++] = tbuf[i];
        buf[l++] = 0;
        CSA(buf);
        CHA(buf);

        for (maxi = 0,  i = 1; i < l; i++)
            if ((sa[i] < l1 && sa[i - 1] > l1) || (sa[i - 1] < l1 && sa[i] > l1))
                if (heigth[i] > maxi) maxi = heigth[i];
        printf("%d\n", maxi);
    }
    return 0;
}
 
#include<iostream>
#include<string>
using namespace std;
#define MAXI 200011

char str[MAXI];
int *sa = new int [MAXI];
int *tsa = new int [MAXI];
int *rank = new int [MAXI];
int *k1 = new int [MAXI];
int *k2 = new int [MAXI];
int *t, l, hash[MAXI], height[MAXI];

void CSA()
{
    int i, j, k, sigm = MAXI;
    for (i = 0; i < sigm; i++) hash[i] = 0;
    for (i = 0; i < l; i++) hash[k1[i] = str[i]]++;
    for (i = 1; i < sigm; i++) hash[i] += hash[i - 1];
    for (i = l - 1; i >= 0; i--) sa[--hash[str[i]]] = i;
    for (j = 1; j < l; j <<= 1, sigm++)
    {
        for (k = 0, i = l - j; i < l; i++) tsa[k++] = i;
        for (i = 0; i < l; i++)  if (sa[i] >= j) tsa[k++] = sa[i] - j;
        for (i = 0; i < l; i++) k2[i] = k1[sa[i]];
        for (swap(sa, tsa), i = 0; i < sigm; i++) hash[i] = 0;
        for (i = 0; i < l; i++) hash[k1[sa[i]]]++;
        for (i = 1; i < sigm; i++) hash[i] += hash[i - 1];
        for (i = l - 1; i >= 0; i--) tsa[--hash[k1[sa[i]]]] = sa[i];
        swap(sa, tsa); swap(k1, k2);
        for (sigm = k1[sa[0]] = 0, i = 1; i < l; i++)
            if (k2[sa[i]] == k2[sa[i - 1]] && k2[sa[i] + j] == k2[sa[i - 1] + j])
                k1[sa[i]] = sigm;
            else k1[sa[i]] = ++sigm;
    }
    for (i = 0; i < l; i++) rank[sa[i]] = i;
}

void CHA()
{
    int i, add;
    for (i = 0; i < l; i++)
        if (rank[i] == 0) height[rank[i]] = 0;
        else
        {
            if (i == 0 || height[rank[i - 1]] <= 1) add = 0;
            else add = height[rank[i - 1]] - 1;
            while (str[sa[rank[i]] + add] == str[sa[rank[i] - 1] + add]) add++;
            height[rank[i]] = add;
        }
}

int main()
{
    int i, l1, l2, maxi;
    char tbuf[MAXI];

    while (scanf("%s", tbuf) != EOF)
    {
        l1 = strlen(tbuf);
        for (i = l = 0; i < l1; i++) str[l++] = tbuf[i];
        str[l++] = '#';
        scanf("%s", tbuf);
        l2 = strlen(tbuf);
        for (i = 0; i < l2; i++) str[l++] = tbuf[i];
        str[l++] = 0;
        CSA(), CHA();
        for (maxi = 0, i = 1; i < l; i++)
            if ((sa[i] < l1 && sa[i - 1] > l1) || (sa[i - 1] < l1 && sa[i] > l1))
                if (height[i] > maxi) maxi = height[i];
        printf("%d\n", maxi);
    }

    return 0;
}
 
{= =*}Y
 
经过左今次优化之后我觉得…………可能对key1排序都可以好似key2甘直接得出!!
不过都系搞下其他先啦,因为就快省赛鸟………………

 

你可能感兴趣的:(C++,算法,substring,common,longest)