您的位置:首页 > 其它

Hdu1403 Longest Common Substring

2018-03-11 13:45 399 查看

Longest Common Substring

Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 7335 Accepted Submission(s): 2580


[align=left]Problem Description[/align]
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.
[align=left]Input[/align]
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.
[align=left]Output[/align]
For each test case, you have to tell the length of the Longest Common Substring of them.
[align=left]Sample Input[/align]

banana
cianaic

[align=left]Sample Output[/align]

3

[align=left]Author[/align]
Ignatius.L
题目大意:求两个字符串的后缀的LCP.
分析:后缀数组的经典应用.
   把两个字符串拼起来,中间用一个特殊字符隔开.对这一整体字符串求height数组,如果height[i]比ans大,并且sa[i-1],sa[i]分布在两个字符串中,就更新ans.
   注意多组数据数组清空的问题!我没有清空fir和sec数组,导致一直RE.

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int maxn = 1000010;
char s1[maxn],s2[maxn],s[maxn];
int len1,len2,len,sett[maxn],a[maxn],cnt,fir[maxn],sec[maxn],tong[maxn],pos[maxn];
int rk[maxn],sa[maxn],ht[maxn],ans,poss;

void solve()
{
memset(rk,0,sizeof(rk));
memset(sa,0,sizeof(sa));
memset(ht,0,sizeof(ht));
memset(fir,0,sizeof(fir));
memset(sec,0,sizeof(sec));
memset(pos,0,sizeof(pos));
memset(tong,0,sizeof(tong));
copy(s + 1,s + len + 1,sett + 1);
sort(sett + 1,sett + 1 + len);
cnt = unique(sett + 1,sett + 1 + len) - sett - 1;
for (int i = 1; i <= len; i++)
a[i] = lower_bound(sett + 1,sett + 1 + cnt,s[i]) - sett;
for (int i = 1; i <= len; i++)
tong[a[i]]++;
for (int i = 1; i <= len; i++)
tong[i] += tong[i - 1];
for (int i = 1; i <= len; i++)
rk[i] = tong[a[i] - 1] + 1;
for (int t = 1; t <= len; t *= 2)
{
for (int i = 1; i <= len; i++)
fir[i] = rk[i];
for (int i = 1; i <= len; i++)
{
if (i + t > len)
sec[i] = 0;
else
sec[i] = rk[i + t];
}
fill(tong,tong + 1 + len,0);
for (int i = 1; i <= len; i++)
tong[sec[i]]++;
for (int i = 1; i <= len; i++)
tong[i] += tong[i - 1];
for (int i = 1; i <= len; i++)
pos[len - --tong[sec[i]]] = i;
fill(tong,tong + 1 + len,0);
for (int i = 1; i <= len; i++)
tong[fir[i]]++;
for (int i = 1; i <= len; i++)
tong[i] += tong[i - 1];
for (int i = 1; i <= len; i++)
{
int temp = pos[i];
sa[tong[fir[temp]]--] = temp;
}
bool flag = true;
int last = 0;
for (int i = 1; i <= len; i++)
{
int temp = sa[i];
if (!last)
rk[temp] = 1;
else if (fir[temp] == fir[last] && sec[temp] == sec[last])
{
rk[temp] = rk[last];
flag = false;
}
else
rk[temp] = rk[last] + 1;
last = temp;
}
if (flag)
break;
}
int k = 0;
for (int i = 1; i <= len; i++)
{
if (rk[i] == 1)
k = 0;
else
{
if (k)
k--;
int j = sa[rk[i] - 1];
while (i + k <= len && j + k <= len && a[i + k] == a[j + k])
k++;
}
ht[rk[i]] = k;
}
}

int main()
{
while (~scanf("%s",s1 + 1))
{
len = ans = 0;
len1 = strlen(s1 + 1);
scanf("%s",s2 + 1);
len2 = strlen(s2 + 1);
for (int i = 1; i <= len1; i++)
s[++len] = s1[i];
s[++len] = '&';
poss = len;
for (int i = 1; i <= len2; i++)
s[++len] = s2[i];
solve();
for (int i = 2; i <= len; i++)
if (ht[i] > ans && ((sa[i - 1] < poss && sa[i] > poss) || (sa[i - 1] > poss && sa[i] < poss)))
ans = ht[i];
printf("%d\n",ans);
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: