poj 2774 最长公共子--弦hash或后缀数组或后缀自己主动机
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或后缀数组或后缀自己主动机的更多相关文章
- poj 2774 最长公共子串 后缀数组
Long Long Message Time Limit: 4000MS Memory Limit: 131072K Total Submissions: 25752 Accepted: 10 ...
- POJ 2774 最长公共子串
一定好好学SAM...模板在此: #include<iostream> #include<cstdio> #include<cmath> #include<a ...
- 使用后缀数组寻找最长公共子字符串JavaScript版
后缀数组很久很久以前就出现了,具体的概念读者自行搜索,小菜仅略知一二,不便讨论. 本文通过寻找两个字符串的最长公共子字符串,演示了后缀数组的经典应用. 首先需要说明,小菜实现的这个后缀数组算法,并非标 ...
- uva 10066 The Twin Towers (最长公共子)
uva 10066 The Twin Towers 标题效果:最长公共子. 解题思路:最长公共子. #include<stdio.h> #include<string.h> # ...
- POJ 1458 最长公共子序列(dp)
POJ 1458 最长公共子序列 题目大意:给出两个字符串,求出这样的一 个最长的公共子序列的长度:子序列 中的每个字符都能在两个原串中找到, 而且每个字符的先后顺序和原串中的 先后顺序一致. Sam ...
- POJ 1159 Palindrome-最长公共子序列问题+滚动数组(dp数组的重复利用)(结合奇偶性)
Description A palindrome is a symmetrical string, that is, a string read identically from left to ri ...
- (持续更新)虚树,KD-Tree,长链剖分,后缀数组,后缀自动机
真的就是讲课两天,吸收一个月呢! \(1.\)虚树 \(2.\)KD-Tree \(3.\)长链剖分 \(4.\)后缀数组 后缀数组 \(5.\)后缀自动机 后缀自动机
- POJ 2774 Long Long Message (二分 + Hash 求最长公共子串)题解
题意:求最长公共子串 思路:把两个串Hash,然后我们把短的作为LCS的最大可能值,然后二分长度,每次判断这样二分可不可以.判断时,先拿出第一个母串所有len长的子串,排序,然后枚举第二个母串len长 ...
- POJ 2774 后缀数组:查找最长公共子
思考:其实很easy.就在两个串在一起.通过一个特殊字符,中间分隔,然后找到后缀数组的最长的公共前缀.然后在两个不同的串,最长是最长的公共子串. 注意的是:用第一个字符串来推断是不是在同一个字符中,刚 ...
随机推荐
- 编码规范(HTML)
code { font-family: "PT Mono", Menlo, "Courier New", monospace; padding: 2px 4px ...
- XSS第二节,XSS左邻右舍
昨天的文章中引用了OWASP2013年的江湖排名,今天来看一下TOP中XSS的左邻右舍都是谁,先看一下他们的大名,再进一步介绍 [以下主要翻译自https://www.owasp.org/index. ...
- js获取名字为XX的标签
$("input[name='XX']"); <input name="address_select" type="radio" va ...
- Oracle监听静态注册和动态注册
静态注册和动态注册总结 一.什么是注册? 注册就是将数据库作为一个服务注册到监听程序.客户端不需要知道数据库名和实例名,只需要知道该数据库对外提供的服务名就可以申请连接到数据库.这个服务名可能与实例名 ...
- stm32之通用定时器TIM
STM32系列的CPU,有多达8个定时器: 1.其中TMI1和TIM8是能够产生三对PWM互补输出的高级定时器,常用于三相电机的驱动:它们的时钟有APB2的输出产生: 2.其它6个为普通定时器,时钟由 ...
- css-文字
<!DOCTYPE html>CSS2-文字 <style>div{ /*文字*/ font-size:120px; /*文字大小*/ font-family:Arial,'方 ...
- FullCalendar 的学习笔记(二)
下面是一个.NET webForm的具体列子 注意引用了artDialog 以及异步请求数据的json格式字符串 <html xmlns="http://www.w3.org/1999 ...
- baidu地图的一个拾取坐标系统
http://api.map.baidu.com/lbsapi/getpoint/index.html 可以很方便的通过标记取得经纬度坐标 也可以输入经纬度坐标获得地图标记
- C# List<T>的详细用法
所属命名空间:System.Collections.Generic List<T>类是 ArrayList 类的泛型等效类.该类使用大小可按需动态增加的数组实现 IList<T> ...
- OpenCV——Haar-like特征
Haar-like特征--即Haar特征,是计算机视觉领域一种常用的特征描述算子.它最早用于人脸描述. 目前常用的Haar-like特征可以分为以下几类:线性特征.边缘特征.点特征(中心特征).对角线 ...