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. OpenGL——点的绘制(使用OpenGL来绘制可旋转坐标系的螺旋线)

    package com.example.opengl1; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio. ...

  2. Ant命令行操作

    Ant命令行操作 Ant构建文件可以将项目编译,打包,測试,它是Apache软件基金会jakarta文件夹中的一个子项目,具有跨平台性,操作简单,并且非常easy上手. 关于Ant执行,能够在项目中找 ...

  3. 国内外移动端web适配屏幕方案

    基础知识点 设备像素:设备像素又称物理像素(physical pixel),设备能控制显示的最小单位,我们可以把这些像素看作成显示器上一个个的点. iPhone5的物理像素是640X1136. PS: ...

  4. ORACLE数据库常用查询二

    ORACLE数据库常用查询 1.查看表空间对应数据文件情况: SQL MB,AUTOEXTENSIBLE FROM DBA_DATA_FILES; TABLESPACE_NAME FILE_NAME ...

  5. Oracle11g x64使用Oracle SQL Developer报错:Unable to find a Java Virtual Machine

    原因oracle 11g中安装的Oracle SQL Developer是32位的,而我们现在给他指定的java.exe却是64位的,所以会出现这种错误.解决方法1)从网上下载Oracle SQL D ...

  6. [HeadFist-HTMLCSS学习笔记][第四章Web镇之旅]

    重要 访问一个目录,即是访问他的index <a>链接到网站,必须加http:// <a>的title属性,能预先知道链接信息 id属性 使得<a> 能再本地跳转. ...

  7. HTML5+CSS3项目总结

      经过一个月的学习,我基本掌握了HTML5的一些标签的用法和特性,以及一些CSS3的属性的特点和用法. 在本周安排的为期四天的第一阶段的课程的项目实训中,我基本能够熟练运用学到的知识,完成页面的速度 ...

  8. 使用VS调试64位应用程序

    VS2012开始,就自带IIS Express,相比先前VS的Web调试器的弱智,和IIS的繁琐,Express简直是最佳方式啦. 本机环境是64位Win7 + 64位Oracle Client,调试 ...

  9. Android 定义重名权限问题

    一直以来对android的权限机制就有一个疑问,因为在使用权限时,实际上只需要permission的name这一个标签,而在定义权限时,android是不会检查是否重名的,那么在两个应用定义了重名权限 ...

  10. lucene评分推导公式

    在进行Lucene的搜索过程解析之前,有必要单独的一张把Lucene score公式的推导,各部分的意义阐述一下.因为Lucene的搜索过程,很重要的一个步骤就是逐步的计算各部分的分数. Lucene ...