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. Non-negative Partial Sums(单调队列)

    Non-negative Partial Sums Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/32768 K (Jav ...

  2. Number of Parallelograms(求平行四边形个数)

    Number of Parallelograms time limit per test 4 seconds memory limit per test 256 megabytes input sta ...

  3. Android应用切换皮肤功能实现(二)

    原文地址http://www.apkbus.com/forum.php?mod=viewthread&tid=149034&highlight=%E7%9A%AE%E8%82%A4 上 ...

  4. 一道movfuscator混淆过的简单逆向

        月赛中出了道经过movfuscator混淆的逆向题目,记录一下过程.跑起来发现需要用户输入长度为20的字符串,我尝试着输入了几次都是直接退出了,没有任何提示.用IDA打开,题目里面几乎全是mo ...

  5. EffectiveC#03--用委托表示回调,用事件定义对外接口

    1.回调的场景:我给了儿子一个任务且他可以报告状态来(重复的)打断我.而我在等待他完成任务的每一个部份时不用阻塞我自己的进程.他可以在有重要(或者事件)状态报告时,可以定时的打断我,或者向我询求帮助 ...

  6. XML 解析中,如何排除控制字符

    XML 解析中,如何排除控制字符 今天在解析一个中文的 XML时,始终报错 PCDATA invalid Char value 21 in Entity ,查询了一下这个 21 的ascii 值,发现 ...

  7. 优化:代码移动code motion

    代码移动code motion-一种常见的优化-这种优化是把(一种需要执行多次但计算结果不会改变)的计算移到前面-这种优化一般需要程序员自行移动代码,不能依靠编译器(编译器担心会有副作用) 看看代码就 ...

  8. (原+转)ubuntu16中安装opencv2.4.11

    转载请注明出处: http://www.cnblogs.com/darkknightzh/p/5638117.html 参考网址: http://www.cnblogs.com/jeakon/arch ...

  9. git commit的--amend选项

    git commit --amend常常用来修改某个branch上最顶端的commit,大多数情况下,这个命令给人的感觉是用新的commit替换了原来的commit.git commit --amen ...

  10. JSON序列化选项

    JSON.stringify()除了接受序列化js对象外,还可以接受另外的两个参数,这两个参数用于指定使用什么样的方式序列化js对象. 第一个参数是个过滤器,可以一个数组或者一个函数:第二个参数是一个 ...