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.就在两个串在一起.通过一个特殊字符,中间分隔,然后找到后缀数组的最长的公共前缀.然后在两个不同的串,最长是最长的公共子串. 注意的是:用第一个字符串来推断是不是在同一个字符中,刚 ...
随机推荐
- iPhone/iPad全屏截图与区域截图的几种方法
本文由社区会员taonavy分享 截取本区域(self.view): UIGraphicsBeginImageContext(CGSizeMake(self.view.frame.size.width ...
- hdu1016Prime Ring Problem
就是说,给你一个数n, 要你把1到n都连在一起成环. 每一个数不可反复, 且相连的两个数的和要是素数. 把全部情况输出来. 我是用dfs暴力出来的. 首先把素数打表, 然后每次顺时针预測下一个数 ...
- 浅谈Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6627260 在前面一篇文章浅谈Service ...
- SlipButton——滑动开关
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMjI1MjUwMg==/font/5a6L5L2T/fontsize/400/fill/I0JBQk ...
- [hdu5136]Yue Fei's Battle 2014 亚洲区域赛广州赛区J题(dp)
转载请注明出处: http://www.cnblogs.com/fraud/ ——by fraud 现场赛的时候由于有个地方有点小问题,没有成功AC,导致与金牌失之交臂. 由于今天下 ...
- [Leetcode] Find the minimum in rotated sorted array
我在Github上新建了一个解答Leetcode问题的Project, 大家可以参考, 目前是Java 为主,里面有leetcode上的题目,解答,还有一些基本的单元测试,方便大家起步. 题目: Su ...
- 17款提高编程效率的css工具
参看下面链接:<17款提高编程效率的css工具>
- MYSQL操作的一些知识点,持续更新中····
基本概念——库 1.数据库服务器:库——>表——>行/列 2.cmd下链接: mysql – uroot –proot 3.创建库:create database php; 3.看数据库 ...
- java 数字补齐0
String str_f = str.substring(0, 1); int i = (Integer.parseInt(str.substring(1)) + 1); // 数字补齐0 Decim ...
- Joomla 二次开发 学习笔记
Joomla目录结构 /administrator 管理后台的路径 /cache 是缓存目录 /components 是组件(component)目录 /includes 是一个重要的目录,里面都是J ...