POJ2774(二分+哈希)

Long Long Message

Time Limit: 4000MS   Memory Limit: 131072K
Total Submissions: 27234   Accepted: 11084
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
 1 //2016.9.8
 2 #include <iostream>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <algorithm>
 6 #define ull unsigned long long
 7
 8 using namespace std;
 9
10 const int N = 100005;
11 char s1[N], s2[N];
12 int len1, len2;
13 ull h1[N], h2[N], a[N], Pow[N];
14
15 ull get_hash(ull *h, int l, int r)
16 {
17     return h[r]-h[l]*Pow[r-l];
18 }
19
20 bool solve(int len)
21 {
22     int cnt = 0;
23     for(int i = len; i <= len1; i++)
24           a[cnt++] = get_hash(h1, i-len, i);
25     sort(a, a+cnt);
26     for(int i = len; i <= len2; i++)
27     {
28         ull h = get_hash(h2, i-len, i);
29         if(binary_search(a, a+cnt, h))
30               return true;
31     }
32     return false;
33 }
34
35 int main()
36 {
37     scanf("%s%s", s1, s2);
38     len1 = strlen(s1);
39     len2 = strlen(s2);
40     int l = 0, r = max(len1, len2), mid;
41     Pow[0] = 1;
42     for(int i = 1; i <= r; i++)
43           Pow[i] = Pow[i-1]*131;
44     h1[0] = h2[0] = 0;
45     for(int i = 0; i < len1; i++)
46           h1[i+1] = h1[i]*131+s1[i];
47     for(int i = 0; i < len2; i++)
48           h2[i+1] = h2[i]*131+s2[i];
49     while(l < r)
50     {
51         mid = (l+r)>>1;
52         if(solve(mid+1))l = mid+1;
53         else r = mid;
54     }
55     printf("%d\n", l);
56
57     return 0;
58 }
时间: 2024-12-18 06:03:19

POJ2774(二分+哈希)的相关文章

用 二分+哈希 求后缀数组

个人感觉后缀数组的板子太难背了,听了小火车讲二分+哈希可以实现求后缀数组,貌似很好理解,代码如下. 1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<cmath> 6 #include<algorithm> 7 #include<queue> 8 #include<vector>

POJ 2774 后缀数组 || 二分+哈希

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

POJ-2774 字符串哈希+二分

题意:给出s,t两个字符串,求最长公共子串的长度 思路:首先二分答案x,预处理出s中长度为x的子串哈希值并排序,在t中枚举起点,二分查找t[i...i+x]的哈希值 二分查找直接用binary_search()函数 复杂度其实是nlog方 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<iostream> 5 #define LL long long 6 #def

哈希是好东西,二分+哈希是更好的东西

rt 明明能哈希为什么要KMP/AC自动机/后缀数组/后缀自动机/后缀树呢??????? [XSY2361]LCP 给定串 S,m 组询问 (X, Y, L, R): 求 S[X:Y] 与 S[L:R] 的最长公共前缀. 1 #include<algorithm> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdio> 5 #include<cmath> 6 #include<

【CodeForces】961 F. k-substrings 字符串哈希+二分

[题目]F. k-substrings [题意]给定长度为n的串S,对于S的每个k-子串$s_ks_{k+1}...s_{n-k+1},k\in[1,\left \lceil \frac{n}{2} \right \rceil]$,找到满足[奇数长度][严格子串][同时是前缀和后缀]的最长子串.n<=10^6. [算法]字符串哈希+二分 [题解]任意两个对应子串,它们有一个不变量--它们的中心一定是i和n-i+1.而且固定中心之后,能延伸的最长相等子串是可以二分+哈希得到的. 所以枚举k,二分+

BZOJ 2084 二分+hash OR Manacher

思路: 二分+哈希 //By SiriusRen #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int N=500050; const ll mod=1000000007; int n; ll hs1[N],hs2[N],base[N],Ans; char s1[N],s2[N]; int main(){

bzoj 1014[JSOI2008]火星人prefix - 二分 + hash + splay

我们发现要支持修改操作,所以后缀数组就不适用了 查询两个字符串的lcp有两个很常见的算法, 后缀数组和 二分哈希 所以对于字符串的修改我们用一个splay 来维护, 平衡树每个节点表示的是对应子树的字符串的哈希值. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #define LL long long 6 using namesp

bzoj1014

splay+二分+哈希 splay维护区间哈希值,每次二分长度 调了很长时间,主要是两个错误:1.提取区间应该是pos+1,pos+2,因为现在在开头放了一个?,所以现在应该是位置比pos+1大,比pos+2小 2.二分边界,因为多加了两个字符,所以原串长度应该是cnt-2,那么二分边界应该是-1->len+1,也就是-1>cnt-y,因为cnt=n+2,串的最大长度应该小于结尾,所以y+len-1<=n,y+len-1<=cnt-2,所以应该是len<=cnt-y-1,又因

BZOJ 1014 火星人prefix

Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 8 9 10 11 字符 m a d a m i m a d a m 现在,火星人定义了一个函数LCQ(x, y),表示:该字符串中第x个字符开始的字串,与该字符串中第y个字符开始的字串,两个字串的公共前缀的长度.比方说,LCQ(1, 7) = 5, LCQ(2, 10) = 1, LCQ(4,