POJ 2774 字符串哈希_解题报告

题目:

 http://poj.org/problem?id=2774

A - Long Long Message

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

题目大意:输出两个字符串中最长字串的长度,两个串长不超过100000.

思路:

  二分子串长度,通过哈希值验证两个字符串是否存在该长度的子串。

首先比较两个字符串的长短,选取较短的长度作为r值,l值初始为0(注意是0,不是1!!可能没有公共子串!)。求出一个字符串前缀的哈希值,存储在数组里。

判断是否有长度为mid的字串:通过长为mid的哈希值,O(n)求出所有长为mid的哈希值,存储在数组里,排序。依次求出另一个字符串长为mid的所有字串的哈希值,binary_search查找是否存在字串。

复杂度:sort +  lower_bound  (n2logn)

出错的地方:

这道题用了unsigned long
long 到达264自然溢出,所以没有显式地用模运算,但是要注意所有用来计算哈希值的变量都应该是unsigned long long ,否则就会造成模数不同而出错!

二分答案左值初始应设为0,可能没有公共子串!!

AC代码:

 1 #include <iostream>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cstdio>
 5 using namespace std;
 6 typedef unsigned long long ull;
 7 const int maxn=1e5+10;
 8 char stra[maxn],strb[maxn],strc[maxn];
 9 ull hasa[maxn],hasb[maxn];
10 int lena,lenb;
11 ull mi[maxn];
12 ull hasat[maxn],hasbt;   //这里应该用ull,因为用来存储哈希值
13 bool yes(int x){
14     hasat[0]=hasa[x-1];
15     for(int i=1;i<lena-x+1;i++){
16         hasat[i]=hasat[i-1]*31+stra[i+x-1]-‘a‘+1-(ull)(stra[i-1]-‘a‘+1)*mi[x];
17     }
18     sort(hasat,hasat+lena-x+1);
19     hasbt=hasb[x-1];
20     for(int i=1;i<lenb-x+2;i++){
21         if(binary_search(hasat,hasat+lena-x+1,hasbt)) return true;
22         hasbt=hasbt*31+strb[i+x-1]-‘a‘+1-(ull)(strb[i-1]-‘a‘+1)*mi[x];
23     }
24
25     return false;
26 }
27 int main(int argc, char** argv) {
28     mi[0]=1;     //预处理31的各个幂
29     for(int i=1;i<maxn;i++) mi[i]=mi[i-1]*31;
30     while(scanf("%s%s",stra,strb)==2){
31         lena=strlen(stra),lenb=strlen(strb);
32         if(lena>lenb){    //短的是字符串a
33             int temp=lena;
34             lena=lenb;
35             lenb=temp;
36             strcpy(strc,stra);
37             strcpy(stra,strb);
38             strcpy(strb,strc);
39         }
40         hasb[0]=strb[0]-‘a‘+1;     //预处理字符串b
41         for(int i=1;i<lenb;i++){
42             hasb[i]=strb[i]-‘a‘+1+hasb[i-1]*31;   //为什么不从0开始?因为这样就容易出现不同字符串哈希值相等的情况
43         }
44         hasa[0]=stra[0]-‘a‘+1;     //预处理字符串b
45         for(int i=1;i<lena;i++){
46             hasa[i]=stra[i]-‘a‘+1+hasa[i-1]*31;   //为什么不从0开始?因为这样就容易出现不同字符串哈希值相等的情况
47         }
48     //    cout<<"ok"<<endl;
49         int l=0,r=lena,mid;    //l应该初始时0!!!可能有0的情况!!
50         while(l<r-1){
51             mid=(l+r)>>1;
52             if(yes(mid)) l=mid;
53             else r=mid-1;
54         }
55     //    cout<<"okk"<<endl;
56     //    cout<<l<<" "<<r<<endl;
57         for(int i=r;i>=l;i--){
58             if(yes(i)){
59                 cout<<i<<endl;
60                 break;
61             }
62
63         }
64     }
65
66     return 0;
67 }

原文地址:https://www.cnblogs.com/jasmine-/p/11300516.html

时间: 2024-11-07 12:50:37

POJ 2774 字符串哈希_解题报告的相关文章

poj 2774 字符串哈希求最长公共子串

Long Long Message #include <iostream> #include <algorithm> #include <cstdio> #include <cstdlib> #include <cstring> #include <queue> #include <stack> #include <cmath> #include <map> #include <string&

最小生成树,POJ和HDU几道题目的解题报告(基于自己写的模板)

首先POJ题目: 链接:1251 Jungle Roads 题目大意:纯求最小生成树,结果为最小权值边的和.采用邻接表 代码: 1 #include <iostream> 2 #include <cstdio> 3 #include <vector> 4 #include <queue> 5 using namespace std; 6 7 #define maxn 30 //最大顶点个数 8 int n; //顶点数,边数 9 10 struct arcn

poj 1094 Sorting It All Out 解题报告

题目链接:http://poj.org/problem?id=1094 题目意思:给出 n 个待排序的字母 和 m 种关系,问需要读到第 几 行可以确定这些字母的排列顺序或者有矛盾的地方,又或者虽然具体的字母顺序不能确定但至少不矛盾.这些关系均是这样的一种形式: 字母1 < 字母2 这道题目属于图论上的拓扑排序,由于要知道读入第几行可以确定具体的顺序,所以每次读入都需要进行拓扑排序来检验,这时每个点的入度就需要存储起来,所以就有了代码中memcpy 的使用了. 拓扑排序的思路很容易理解,但写起来

POJ 1788 Building a New Depot 解题报告

Description Advanced Cargo Movement, Ltd. is successfully expanding. In order to meet new demands on truck maintenance, the management of the company decided to build a new truck depot. A suitable lot for building a depot was purchased and a construc

POJ 3126(BFS_E题)解题报告

题目链接:http://poj.org/problem?id=3126 -------------------------------------------------------- 题意:给定两个数,将初始数,每次变换一位而且必须保证变换后的数为素数,要求从初始数到目标数所需要的最小操作次数. 思路:首先是多组测试数据,所以先打个10000以内的素数表,防止每次都去判断.然后就是bfs的想法,每次分别改变个位.十位.百位.千位的值,然后按层次进行遍历,首先到达的情况是最小值的情况. 代码:

poj 1087.A Plug for UNIX 解题报告

网络流,关键在建图 建图思路在代码里 /* 最大流SAP 邻接表 思路:基本源于FF方法,给每个顶点设定层次标号,和允许弧. 优化: 1.当前弧优化(重要). 1.每找到以条增广路回退到断点(常数优化). 2.层次出现断层,无法得到新流(重要). 时间复杂度(m*n^2) */ #include <iostream> #include <cstdio> #include <cstring> #include <map> #define ms(a,b) mem

分糖果_解题报告_SSL2339_tyvj1083_spfa

Description 童年的我们,将和朋友分享美好的事物作为自己的快乐.这天,C小朋友得到了Plenty of candies,将要把这些糖果分给要好的朋友们.已知糖果从一个人传给另一个人需要1 秒的时间,同一个小朋友不会重复接受糖果.由于糖果足够多,如果某时刻某小朋友接受了糖果,他会将糖果分成若干份,分给那些在他身旁且还没有得到糖果的小朋友们,而且自己会吃一些糖果.由于嘴馋,小朋友们等不及将糖果发完,会在得到糖果后边吃边发.每个小朋友从接受糖果到吃完糖果需要m秒的时间.那么,如果第一秒C小朋

加分二叉树_解题报告_SSL1033_2003年分区联赛提高组之三_树形dp

Description 设一个n个节点的二叉树tree的中序遍历为(l,2,3,-,n),其中数字1,2,3,-,n为节点编号.每个节点都有一个分数(均为正整数),记第j个节点的分数为di,tree及它的每个子树都有一个加分,任一棵子树subtree(也包含tree本身)的加分计算方法如下: subtree的左子树的加分× subtree的右子树的加分+subtree的根的分数 若某个子树为主,规定其加分为1,叶子的加分就是叶节点本身的分数.不考虑它的空 子树. 试求一棵符合中序遍历为(1,2,

POJ 2258(DFS_D题)解题报告

题目链接:https://vjudge.net/problem/22345/origin -------------------------------------------------------------------- 题意:求图中所有路径中最长的路径. 思路:DFS,注意:其中结点可以重复遍历,而边不可以重复遍历.所以应当在深度遍历上做一定修改,将对结点的遍历改为对边的遍历. 代码: #include<cstdio> #include<cstring> #include&