Long Long Message
Time Limit: 4000MS   Memory Limit: 131072K
Total Submissions: 35607   Accepted: 14275
Case Time Limit: 1000MS

Description

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.

The little cat lives in an unrich family, so he frequently comes to the mobile service center, to check how much money he has spent on SMS. Yesterday, the computer of service center was broken, and printed two very long messages. The brilliant little cat soon found out:

1. All characters in messages are lowercase Latin letters, without punctuations and spaces.

2. All SMS has been appended to each other – (i+1)-th SMS comes directly after the i-th one – that is why those two messages are quite long.

3. His own SMS has been appended together, but possibly a great many redundancy characters appear leftwards and rightwards due to the broken computer.

E.g: if his SMS is “motheriloveyou”, either long message printed by that machine, would possibly be one of “hahamotheriloveyou”, “motheriloveyoureally”, “motheriloveyouornot”, “bbbmotheriloveyouaaa”, etc.

4. For these broken issues, the little cat has printed his original text twice (so there appears two very long messages). Even though the original text remains the same in two printed messages, the redundancy characters on both sides would be possibly different.

You are given those two very long messages, and you have to output the length of the longest possible original text written by the little cat.

Background:

The SMS in Byterland mobile service are charging in dollars-per-byte. That is why the little cat is worrying about how long could the longest original text be.

Why ask you to write a program? There are four resions:

1. The little cat is so busy these days with physics lessons;

2. The little cat wants to keep what he said to his mother seceret;

3. POJ is such a great Online Judge;

4. The little cat wants to earn some money from POJ, and try to persuade his mother to see the doctor :(

Input

Two strings with lowercase letters on two of the input lines individually. Number of characters in each one will never exceed 100000.

Output

A single line with a single integer number – what is the maximum length of the original text written by the little cat.

Sample Input

yeshowmuchiloveyoumydearmotherreallyicannotbelieveit
yeaphowmuchiloveyoumydearmother

Sample Output

27

这个题目百来就是一道后缀数组的入门题,然后发现二分哈希也能做,于是就都打打。。。

后缀数组:432ms
 #include <algorithm>
#include <iostream>
#include <cstdio>
#include <cstring> using namespace std; const int N = ; int l1, m, n, l2;
int c[N], x[N], y[N], sa[N], ht[N], rk[N];
char s1[N], s2[N], s[N]; inline void Get_Sa()
{
for (int i = ; i <= n; ++i) ++c[x[i] = s[i]];
for (int i = ; i <= m; ++i) c[i] += c[i - ];
for (int i = n; i >= ; --i) sa[c[x[i]]--] = i;
for (int k = ; k <= n; k <<= )
{
int num = ;
for (int i = n - k + ; i <= n; ++i) y[++num] = i;
for (int i = ; i <= n; ++i) if (sa[i] > k) y[++num] = sa[i] - k;
for (int i = ; i <= m; ++i) c[i] = ;
for (int i = ; i <= n; ++i) ++c[x[i]];
for (int i = ; i <= m; ++i) c[i] += c[i - ];
for (int i = n; i >= ; --i) sa[c[x[y[i]]]--] = y[i], y[i] = ;
for (int i = ; i <= n; ++i) y[i] = x[i], x[i] = ;
swap(x, y), x[sa[]] = , num = ;
for (int i = ; i <= n; ++i)
x[sa[i]] = (y[sa[i]] == y[sa[i - ]] && y[sa[i] + k] == y[sa[i - ] + k]) ? num : ++num;
if (num == n) break; m = num;
}
for (int i = ; i <= n; ++i) rk[sa[i]] = i;
} inline void Get_Ht()
{
int k = ;
for (int i = ; i <= n; ++i)
{
if (rk[i] == ) continue;
if (k) --k;
int j = sa[rk[i] - ];
while (j + k <= n && i + k <= n
&& s[i + k] == s[j + k]) ++k;
ht[rk[i]] = k;
}
} int main()
{
while (~scanf("%s%s", s + , s2 + ))
{
int ans = -;
l1 = strlen(s + );
l2 = strlen(s2 + );
s[l1 + ] = '$';
m = ;
for (int i = ; i <= l2; ++i)
s[l1 + + i] = s2[i];
n = strlen(s + );
Get_Sa(), Get_Ht();
for (int i = ; i <= n; ++i)
if (sa[i - ] >= && sa[i - ] <= l1 && sa[i] >= l1 + )
ans = max(ans, ht[i]);
else if (sa[i] >= && sa[i] <= l1 && sa[i - ] >= l1 + )
ans = max(ans, ht[i]);
// for (int i = 1; i <= n; ++i)
// printf("%s %d\n", s + sa[i], ht[i]);
printf("%d\n", ans);
}
return ;
}

二分+哈希:1463ms

 #include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio> using namespace std;
typedef unsigned long long ull; const ull N = ;
const ull base = ; int l1, l2, L, R;
ull bit[N], f[N], h1[N], h2[N];
char s2[N], s1[N]; inline bool good(int l)
{
int tot = ;
for (int i = ; i <= l1 - l + ; ++i)
f[++tot] = h1[i + l - ] - h1[i - ] * bit[l];
sort(f + , f + tot + );
for (int i = ; i <= l2 - l + ; ++i)
if (binary_search(f + , f + tot + , h2[i + l - ] - h2[i - ] * bit[l]))
return true;
return false;
} int main()
{
for (int i = ; i <= N - ; ++i) bit[i] = (i == ? : bit[i - ]) * base;
while (~scanf("%s%s", s1 + , s2 + ))
{
l1 = strlen(s1 + ), l2 = strlen(s2 + );
for (int i = ; i <= l1; ++i) h1[i] = h1[i - ] * base + (s1[i] - );
for (int i = ; i <= l2; ++i) h2[i] = h2[i - ] * base + (s2[i] - );
L = , R = max(l1, l2) + ;
while (L <= R)
{
int mid = (L + R) >> ;
if (good(mid)) L = mid + ;
else R = mid - ;
}
printf("%d\n", R);
}
return ;
}

(虽然慢一点,但哈希真的好写!!!!)

POJ 2774 后缀数组 || 二分+哈希的更多相关文章

  1. POJ 2774 后缀数组

    题目链接:http://poj.org/problem?id=2774 题意:给定两个只含小写字母的字符串,求字符串的最长公共子串长度. 思路:根据<<后缀数组——处理字符串的有力工具&g ...

  2. 2016vijos 1-1 兔子的字符串(后缀数组 + 二分 + 哈希)

    题意: 给出一个字符串,至多将其划分为n部分,每一部分取出字典序最大的子串ci,最小化 最大的ci 先看一个简化版的问题: 给一个串s,再给一个s的子串t,问能否通过将串划分为k个部分,使t成为划分后 ...

  3. POJ 2774 后缀数组:查找最长公共子

    思考:其实很easy.就在两个串在一起.通过一个特殊字符,中间分隔,然后找到后缀数组的最长的公共前缀.然后在两个不同的串,最长是最长的公共子串. 注意的是:用第一个字符串来推断是不是在同一个字符中,刚 ...

  4. POJ 3261 (后缀数组 二分) Milk Patterns

    这道题和UVa 12206一样,求至少重复出现k次的最长字串. 首先还是二分最长字串的长度len,然后以len为边界对height数组分段,如果有一段包含超过k个后缀则符合要求. #include & ...

  5. POJ 1743 (后缀数组 二分) Musical Theme

    看来对height数组进行分段确实是个比较常用的技巧. 题意: 一个主题是可以变调的,也就是如果这个主题所有数字加上或者减少相同的数值,可以看做是相同的主题. 一个主题在原串中至少要出现两次,而且一定 ...

  6. poj 2774 后缀数组 两个字符串的最长公共子串

    Long Long Message Time Limit: 4000MS   Memory Limit: 131072K Total Submissions: 31904   Accepted: 12 ...

  7. POJ 3261 后缀数组+二分

    思路: 论文题- 二分+对后缀分组 这块一开始不用基数排序 会更快的(其实区别不大) //By SiriusRen #include <cstdio> #include <cstri ...

  8. Long Long Message POJ - 2774 后缀数组

    The little cat is majoring in physics in the capital of Byterland. A piece of sad news comes to him ...

  9. POJ 2774 (后缀数组 最长公共字串) Long Long Message

    用一个特殊字符将两个字符串连接起来,然后找最大的height,而且要求这两个相邻的后缀的第一个字符不能在同一个字符串中. #include <cstdio> #include <cs ...

随机推荐

  1. c/c++中define用法详解及代码示例

    https://blog.csdn.net/u012611878/article/details/52534622   版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog. ...

  2. 转 mysql 下载 以及安装

    https://blog.csdn.net/kerafan/article/details/78001849 一.MySQL 各个版本区别 ,(都需要编译的 ) 1.MySQL Community S ...

  3. linux中文件的时间属性atime/mtime/ctime

    文件的时间属性的概念 上图第7-9是时间,默认是ctime(文件修改时间),有三种时间属性: modify time        mtime       (文件内容被修改的时间) change ti ...

  4. Spark最简安装

    该环境适合于学习使用的快速Spark环境,采用Apache预编译好的包进行安装.而在实际开发中需要使用针对于个人Hadoop版本进行编译安装,这将在后面进行介绍. Spark预编译安装包下载——Apa ...

  5. ssh无需密码登录linux服务器

    使用下例中ssky-keygen和ssh-copy-id,仅需通过3个步骤的简单设置而无需输入密码就能登录远程Linux主机. ssh-keygen 创建公钥和密钥. ssh-copy-id 把本地主 ...

  6. sql server数据类型char和nchar,varchar和nvarchar,text和ntext

    varchar和nvarchar的区别: varchar(n)长度为 n 个字节的可变长度且非 Unicode 的字符数据.n 必须是一个介于 1 和 8,000 之间的数值.存储大小为输入数据的字节 ...

  7. js统计字符出现次数

    var s = "The rain in Spain falls rain mainly in the rain plain"; var reg = new RegExp(&quo ...

  8. SpringBoot的核心功能

    1.独立运行的Spring项目 SpringBoot可以以jar包的形式独立运行,运行一个SpringBoot项目只需要通过java -jar xx.jar来启动. 2.内嵌Servlet容器 Spr ...

  9. 《Unity預計算即時GI》笔记:二、光照图

    说明 这篇文章是对<Unity預計算即時GI>这个系列文章的笔记. 光照图 什么是光照图 光照图在第三章中有如下的定义,读起来很是费解. 一個光照圖(Chart)是表示一個光照貼圖的區域, ...

  10. 在SQL中查看文件组中有哪些表

    SELECT o.[name], o.[type], i.[name], i.[index_id], f.[name] FROM sys.indexes i INNER JOIN sys.filegr ...