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

我想看看这里的后缀数组:http://blog.csdn.net/u011026968/article/details/22801015

本文主要讲下怎么hash去找

開始的时候写的是O(n^2 logn)算法 果断超时。

。。尽管也用了二分的。。

代码例如以下:

//hash+二分
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <iostream>
#include <cmath>
#include <map>
#include <queue>
using namespace std; #define ls(rt) rt*2
#define rs(rt) rt*2+1
#define ll long long
#define ull unsigned long long
#define rep(i,s,e) for(int i=s;i<e;i++)
#define repe(i,s,e) for(int i=s;i<=e;i++)
#define CL(a,b) memset(a,b,sizeof(a))
#define IN(s) freopen(s,"r",stdin)
#define OUT(s) freopen(s,"w",stdin)
const ull B = 31; /*according to the book*/
const int MAXN = 100000+100;
char a[MAXN],b[MAXN],tmp[MAXN];
int n,m;
ull ah[MAXN]; int C(int len)
{
int pos=m-len+1;
ull t=1,ah=0,bh=0,tmp;
for(int i=0;i<len;i++)
{
t*=B;
ah=ah*B+a[i];
}
tmp=ah;
for(int k=0;k<pos;k++)///////
{ bh=0;
ah=tmp;
for(int i=k;i<k+len;i++)
bh=bh*B+b[i];
for(int i=0;i+len<=n;i++)
{
if(len==27)
{
printf("#k=%d# i=%d ah bh ",k,i);
cout << ah << ' ' << bh << endl;
}
if(ah==bh)
{
//printf("#k=%d# size=%d %s\n",k,strlen(b+k),b+k);
return 1;
}
if(i+len<n)ah=ah*B+a[i+len]-a[i]*t;
}
}
return 0;
} int solve()
{
n=strlen(a),m=strlen(b);// a--long b-short
if(n<m)
{
swap(n,m);
strcpy(tmp,a);
strcpy(a,b);
strcpy(b,tmp);
}
int d=0,up=m+1,mid;
while(up>d+1)
{
mid=(d+up)/2;
if(C(mid))d=mid;
else up=mid;
}
return d;
} int main()
{
IN("poj2774.txt");
while(~scanf("%s%s",a,b))
{
printf("%d\n",solve());
}
return 0;
}

然后參考了队友的写法,改为这么写:

1、预处理出base数组;

2、将test文本串处理,长为len的哈希值存下来。然后排序,

3、计算第一个场为len的模式串的哈希值,每次更新都是O(1)操作了,然后二分查找

这道题写的时候的问题主要还是自己写的下标把自己弄迷糊了,begin=k,那么begin+len指向结尾字符的下一个字符

//hash+二分
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <iostream>
#include <cmath>
#include <map>
#include <queue>
using namespace std; #define ls(rt) rt*2
#define rs(rt) rt*2+1
#define ll long long
#define ull unsigned long long
#define rep(i,s,e) for(int i=s;i<e;i++)
#define repe(i,s,e) for(int i=s;i<=e;i++)
#define CL(a,b) memset(a,b,sizeof(a))
#define IN(s) freopen(s,"r",stdin)
#define OUT(s) freopen(s,"w",stdin)
const ull B = 1e8+7; /*according to the book*/
const int MAXN = 100000+100;
char a[MAXN],b[MAXN],tmp[MAXN];
int n,m;
ull ah[MAXN],base[MAXN]; int C(int len)
{
int pos=m-len+1;
ull bh=0,tmp=0;
for(int i=0;i<len;i++)
tmp=tmp*B+a[i];
ah[0]=tmp;
for(int i=0;i+len<=n;i++)/////////
ah[i+1]=ah[i]*B+a[i+len]-a[i]*base[len];
sort(ah,ah+n-len+1);
for(int i=0;i<len;i++)
bh=bh*B+b[i];
for(int k=0;k<pos;k++)
{
if(binary_search(ah,ah+n-len+1,bh))
{
return 1;
}
bh=bh*B+b[k+len]-b[k]*base[len];
}
return 0;
} int solve()
{
n=strlen(a),m=strlen(b);// a--long b-short
if(n<m)
{
swap(n,m);
strcpy(tmp,a);
strcpy(a,b);
strcpy(b,tmp);
}
int d=0,up=m+1,mid;
while(up>d+1)
{
mid=(d+up)/2;
if(C(mid))d=mid;
else up=mid;
}
return d;
} int main()
{
//IN("poj2774.txt");
base[0]=1;
for(int i=1;i<MAXN;i++)
base[i]=base[i-1]*B;
while(~scanf("%s%s",a,b))
{
printf("%d\n",solve());
}
return 0;
}

版权声明:本文博主原创文章,博客,未经同意不得转载。

poj 2774 最长公共子--弦hash或后缀数组或后缀自己主动机的更多相关文章

  1. poj 2774 最长公共子串 后缀数组

    Long Long Message Time Limit: 4000MS   Memory Limit: 131072K Total Submissions: 25752   Accepted: 10 ...

  2. POJ 2774 最长公共子串

    一定好好学SAM...模板在此: #include<iostream> #include<cstdio> #include<cmath> #include<a ...

  3. 使用后缀数组寻找最长公共子字符串JavaScript版

    后缀数组很久很久以前就出现了,具体的概念读者自行搜索,小菜仅略知一二,不便讨论. 本文通过寻找两个字符串的最长公共子字符串,演示了后缀数组的经典应用. 首先需要说明,小菜实现的这个后缀数组算法,并非标 ...

  4. uva 10066 The Twin Towers (最长公共子)

    uva 10066 The Twin Towers 标题效果:最长公共子. 解题思路:最长公共子. #include<stdio.h> #include<string.h> # ...

  5. POJ 1458 最长公共子序列(dp)

    POJ 1458 最长公共子序列 题目大意:给出两个字符串,求出这样的一 个最长的公共子序列的长度:子序列 中的每个字符都能在两个原串中找到, 而且每个字符的先后顺序和原串中的 先后顺序一致. Sam ...

  6. POJ 1159 Palindrome-最长公共子序列问题+滚动数组(dp数组的重复利用)(结合奇偶性)

    Description A palindrome is a symmetrical string, that is, a string read identically from left to ri ...

  7. (持续更新)虚树,KD-Tree,长链剖分,后缀数组,后缀自动机

    真的就是讲课两天,吸收一个月呢! \(1.\)虚树 \(2.\)KD-Tree \(3.\)长链剖分 \(4.\)后缀数组 后缀数组 \(5.\)后缀自动机 后缀自动机

  8. POJ 2774 Long Long Message (二分 + Hash 求最长公共子串)题解

    题意:求最长公共子串 思路:把两个串Hash,然后我们把短的作为LCS的最大可能值,然后二分长度,每次判断这样二分可不可以.判断时,先拿出第一个母串所有len长的子串,排序,然后枚举第二个母串len长 ...

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

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

随机推荐

  1. 【iOS开发-66】QQ设置界面的案例:利用storyboard开发静态的tableView界面,核心是Static Cells

    (1)效果 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2Vpc3ViYW8=/font/5a6L5L2T/fontsize/400/fill/I0JB ...

  2. HTTP协议报文格式

    HTTP协议报文格式 接下来我们看看HTTP协议(Hypertext Transfer Protocol――超文本传输协议)浏览器端(客户端)向WEB服务器端访问页面的过程和HTTP协议报文的格式. ...

  3. linux磁盘管理、新增磁盘、分区、挂载

    1. du -sh 查看目录.文件总大小 -a:全部文件与目录大小都列出来.如果不加任何选项和参数只列出目录(包含子目录)大小. -c:最后加总2. df -h 查看磁盘使用量3. lsblk 查看系 ...

  4. C#几种截取字符串的方法小结 (摘抄)

    1.根据单个分隔字符用split截取 例如 string st="GT123_1"; string[] sArray=st.split("_"); 即可得到sA ...

  5. shell参数

    shell获取当前执行脚本的路径 filepath=$(cd "$(dirname "$0")"; pwd) 脚本文件的绝对路径存在了环境变量filepath中 ...

  6. CDZSC_2015寒假新人(2)——数学 A

    A - A Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status ...

  7. mysql升级后报Table 'mysql.servers' doesn't exist

    解决Table 'mysql.servers' doesn't exist 今天遇到一事,就是我在升级mysql数据库后进入数据建立一远程用户,结果报错了. mysql> flush privi ...

  8. html标签元素分类

    元素分类 html中的标签元素大体分为三种不同的类型:块状元素.内联元素(又叫行内元素)和内联块状元素. 常用的块状元素有: <div>.<p>.<h1>...&l ...

  9. DOM和jQuery

    一.DOM 在学习DOM之前你应该已经具备了以下三个知识点的应用:HTML CSS javascript DOM 是 W3C(万维网联盟)的标准. W3C DOM 标准被分为 3 个不同的部分: 核心 ...

  10. Python学习(七) 流程控制if语句

    在Python中流程控制if语句采用如下格式: if expression : statement elif expression : statement elif expression : stat ...