poj2774 Long Long Message(后缀数组or后缀自动机)
转载请注明出处: http://www.cnblogs.com/fraud/ ——by fraud
| Time Limit: 4000MS | Memory Limit: 131072K | |
| Case Time Limit: 1000MS | ||
Description
The little cat lives in an unrich family, so he frequently comes to the mobile service center, to check how much money he has spent on SMS. Yesterday, the computer of service center was broken, and printed two very long messages. The brilliant little cat soon found out:
1. All characters in messages are lowercase Latin letters, without punctuations and spaces.
2. All SMS has been appended to each other – (i+1)-th SMS comes directly after the i-th one – that is why those two messages are quite long.
3. His own SMS has been appended together, but possibly a great many redundancy characters appear leftwards and rightwards due to the broken computer.
E.g: if his SMS is “motheriloveyou”, either long message printed by that machine, would possibly be one of “hahamotheriloveyou”, “motheriloveyoureally”, “motheriloveyouornot”, “bbbmotheriloveyouaaa”, etc.
4. For these broken issues, the little cat has printed his original text twice (so there appears two very long messages). Even though the original text remains the same in two printed messages, the redundancy characters on both sides would be possibly different.
You are given those two very long messages, and you have to output the length of the longest possible original text written by the little cat.
Background:
The SMS in Byterland mobile service are charging in dollars-per-byte. That is why the little cat is worrying about how long could the longest original text be.
Why ask you to write a program? There are four resions:
1. The little cat is so busy these days with physics lessons;
2. The little cat wants to keep what he said to his mother seceret;
3. POJ is such a great Online Judge;
4. The little cat wants to earn some money from POJ, and try to persuade his mother to see the doctor :(
Input
Output
Sample Input
yeshowmuchiloveyoumydearmotherreallyicannotbelieveit
yeaphowmuchiloveyoumydearmother
Sample Output
27
Source
题意:
求两个字符串的最长公共子串。
分析:
将两个字符串中间用一个不会出现的'$'符号连接,然后求出lcp,最大的且相邻的两个后缀不属于同一个字符串的就是答案。
用的是DC3
#include <iostream>
#include <sstream>
#include <ios>
#include <iomanip>
#include <functional>
#include <algorithm>
#include <vector>
#include <string>
#include <list>
#include <queue>
#include <deque>
#include <stack>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <climits>
#include <cctype>
using namespace std;
#define XINF INT_MAX
#define INF 0x3FFFFFFF
#define MP(X,Y) make_pair(X,Y)
#define PB(X) push_back(X)
#define REP(X,N) for(int X=0;X<N;X++)
#define REP2(X,L,R) for(int X=L;X<=R;X++)
#define DEP(X,R,L) for(int X=R;X>=L;X--)
#define CLR(A,X) memset(A,X,sizeof(A))
#define IT iterator
typedef long long ll;
typedef pair<int,int> PII;
typedef vector<PII> VII;
typedef vector<int> VI;
#define MAXN 400010 #define F(x) ((x)/3+((x)%3==1?0:tb))
#define G(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2)
int wa[MAXN*],wb[MAXN*],wv[MAXN*],ww[MAXN*]; int c0(int *r, int a, int b) {
return r[a]==r[b]&&r[a+]==r[b+]&&r[a+]==r[b+];
}
int c12(int k, int *r, int a, int b)
{
if(k==) return r[a]<r[b]||r[a]==r[b]&&c12(,r,a+,b+);
else return r[a]<r[b]||r[a]==r[b]&&wv[a+]<wv[b+];
}
void rsort(int *r, int *a, int *b, int n, int m) {
REP(i,n) wv[i]=r[a[i]];
REP(i,m) ww[i]=;
REP(i,n) ww[wv[i]]++;
REP(i,m-) ww[i+]+=ww[i];
DEP(i,n-,) b[--ww[wv[i]]]=a[i];
} void dc3(int *r, int *sa, int n, int m) {
int j,*rn=r+n,*san=sa+n,ta=,tb=(n+)/,tbc=,p;
r[n]=r[n+]=;
REP(i,n) if(i%!=) wa[tbc++]=i;
rsort(r+,wa,wb,tbc,m);
rsort(r+,wb,wa,tbc,m);
rsort(r,wa,wb,tbc,m);
for(p=,rn[F(wb[])]=,j=;j<tbc;j++)
rn[F(wb[j])]=c0(r,wb[j-],wb[j])?p-:p++;
if(p<tbc) dc3(rn,san,tbc,p);
else REP(i,tbc) san[rn[i]]=i;
REP(i,tbc) if(san[i]<tb) wb[ta++]=san[i]*;
if(n%==) wb[ta++]=n-;
rsort(r,wb,wa,ta,m);
REP(i,tbc) wv[wb[i]=G(san[i])]=i;
int i;
for(i=j=p=;i<ta&&j<tbc;p++)
sa[p]=c12(wb[j]%,r,wa[i],wb[j])?wa[i++]:wb[j++];
for(;i<ta;p++) sa[p]=wa[i++];
for(;j<tbc;p++) sa[p]=wb[j++];
} int ra[MAXN*], height[MAXN*];
void calheight(int *r,int *sa,int n) {
int i,j,k=;
for(i=;i<=n;i++) ra[sa[i]]=i;
for(i=;i<n;height[ra[i++]]=k)
for(k?k--:,j=sa[ra[i]-];r[i+k]==r[j+k];k++);
}
int sa[MAXN *];
char str[MAXN];
char s[MAXN];
int a[MAXN];
int main()
{
ios::sync_with_stdio(false);
while(scanf("%s",str)!=EOF){
scanf("%s",s);
int len2=strlen(s);
int len1=strlen(str);
for(int i=;i<len2;i++){
str[i+len1]=s[i];
}
str[len1+len2]='\0';
int len=len1+len2;
for(int i=;i<len;i++){
a[i]=str[i]-'a'+;
}
a[len]=;
dc3(a,sa,len+,);
calheight(a,sa,len);
int ans=;
for(int i=;i<len;i++){
if(sa[i]<len1&&sa[i-]>=len1||(sa[i]>=len1&&sa[i-]<len1)){
ans=max(height[i],ans);
}
}
printf("%d\n",ans);
} return ;
}
代码君
利用后缀自动机的话,以一个串建一个自动机,然后另一个串直接塞进去跑就行了。相当裸
#include <iostream>
#include <sstream>
#include <ios>
#include <iomanip>
#include <functional>
#include <algorithm>
#include <vector>
#include <string>
#include <list>
#include <queue>
#include <deque>
#include <stack>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <climits>
#include <cctype>
using namespace std;
#define XINF INT_MAX
#define INF 0x3FFFFFFF
#define MP(X,Y) make_pair(X,Y)
#define PB(X) push_back(X)
#define REP(X,N) for(int X=0;X<N;X++)
#define REP2(X,L,R) for(int X=L;X<=R;X++)
#define DEP(X,R,L) for(int X=R;X>=L;X--)
#define CLR(A,X) memset(A,X,sizeof(A))
#define IT iterator
#define RIT reverse_iterator
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PII;
typedef vector<PII> VII;
typedef vector<int> VI;
#define X first
#define Y second
#define lson(X) ((X)<<1)
#define rson(X) ((X)<<1|1) #define MAXN 100010 //#define SUFFIX_TREE struct SAM{
SAM* go[];
SAM* par;
int maxl;
#ifdef SUFFIX_TREE
int st_head;
#endif
SAM(int l=):maxl(l) {
#ifdef SUFFIX_TREE
st_head = ;
#endif
}
SAM& operator=(const SAM& s){
maxl = s.maxl;
par = s.par;
memcpy(go, s.go, sizeof(go));
return *this;
#ifdef SUFFIX_TREE
st_head = s.st_head;
#endif
}
int minl() {
return par?par->maxl+:maxl;
}
} node[MAXN<<], *last, *root;
int n_node; SAM* newnode() {
return &node[n_node++];
} void init_sam() {
n_node = ;
last = root = newnode();
} void extend(int c) {
SAM* p = last, *np = newnode();
np->maxl = p->maxl + ;
for(; p && !p->go[c]; p = p->par) p->go[c] = np;
if(!p) np->par = root;
else {
SAM* q = p->go[c];
if(q->maxl == p->maxl + ) np->par = q;
else {
SAM* nq = newnode();
*nq = *q;
nq->maxl = p->maxl + ;
np->par = q->par = nq;
for(;p && p->go[c] == q ;p = p->par) p->go[c] = nq;
}
}
last = np;
#ifdef SUFFIX_TREE
last->st_head = ;
#endif
} string str; #ifdef SUFFIX_TREE VI Map[MAXN<<]; void init_suffixtree(char* s) {
init_sam();
int l = strlen(s);
REP(i,l) extend(s[l-i-]);
REP(i,n_node) Map[i].clear();
REP(i,n_node) if(node[i].st_head) {
SAM* p = &node[i];
while(p!=root) {
string ss = str.substr(p->minl()-,p->maxl-p->minl()+);
reverse(ss.begin(),ss.end());
cout<<ss<<" -> ";
p=p->par;
}
cout<<"|"<<endl;
}
} #endif char s[MAXN]; int main()
{
while(~scanf("%s",s)) {
init_sam();
for(int i=;s[i];i++) extend(s[i]-'a');
scanf("%s",s);
int ans = ;
int l = ;
SAM* now = root;
for(int i=;s[i];i++) {
s[i]-='a';
while(now!=root && now->go[s[i]]==NULL) {
now = now->par;
l = min(l, now->maxl);
}
l++;
if(now->go[s[i]]) now = now->go[s[i]];
else l=;
ans = max(ans, l);
}
printf("%d\n", ans);
}
return ;
}
代码君
poj2774 Long Long Message(后缀数组or后缀自动机)的更多相关文章
- [TJOI2015]弦论(后缀数组or后缀自动机)
解法一:后缀数组 听说后缀数组解第k小本质不同的子串是一个经典问题. 把后缀排好序后第i个串的本质不同的串的贡献就是\(n-sa[i]+1-LCP(i,i-1)\)然后我们累加这个贡献,看到哪一个串的 ...
- (持续更新)虚树,KD-Tree,长链剖分,后缀数组,后缀自动机
真的就是讲课两天,吸收一个月呢! \(1.\)虚树 \(2.\)KD-Tree \(3.\)长链剖分 \(4.\)后缀数组 后缀数组 \(5.\)后缀自动机 后缀自动机
- poj 2774 最长公共子--弦hash或后缀数组或后缀自己主动机
http://poj.org/problem?id=2774 我想看看这里的后缀数组:http://blog.csdn.net/u011026968/article/details/22801015 ...
- hdu4436-str2int(后缀数组 or 后缀自动机)
题意:给你一堆字符串,仅包含数字'0'到'9'. 例如 101 123 有一个字符串集合S包含输入的N个字符串,和他们的全部字串. 操作字符串很无聊,你决定把它们转化成数字. 你可以把一个字符串转换成 ...
- 字符串数据结构模板/题单(后缀数组,后缀自动机,LCP,后缀平衡树,回文自动机)
模板 后缀数组 #include<bits/stdc++.h> #define R register int using namespace std; const int N=1e6+9; ...
- 后缀数组(suffix array)详解
写在前面 在字符串处理当中,后缀树和后缀数组都是非常有力的工具. 其中后缀树大家了解得比较多,关于后缀数组则很少见于国内的资料. 其实后缀数组是后缀树的一个非常精巧的替代品,它比后缀树容易编程实现, ...
- 字符串 --- KMP Eentend-Kmp 自动机 trie图 trie树 后缀树 后缀数组
涉及到字符串的问题,无外乎这样一些算法和数据结构:自动机 KMP算法 Extend-KMP 后缀树 后缀数组 trie树 trie图及其应用.当然这些都是比较高级的数据结构和算法,而这里面最常用和最熟 ...
- bzoj 3172 后缀数组|AC自动机
后缀数组或者AC自动机都可以,模板题. /************************************************************** Problem: 3172 Us ...
- 数据结构之后缀数组suffix array
在字符串处理当中,后缀树和后缀数组都是非常有力的工具,其中后缀树大家了解得比较多,关于后缀数组则很少见于国内的资料.其实后缀是后缀树的一个非常精巧的替代品,它比后缀树容易编程实现,能够实现后缀树的很多 ...
随机推荐
- 探索A@1db9742
public class S { /** * @param args */ public static void main(String[] args) { System.out.printl ...
- poj3122 binary search 实数区间
Pie Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 14536 Accepted: 4979 Special Ju ...
- GTD:是一种态度
时间管理发展的四个阶段: 第一代理论着重利用便条与备忘录,在忙碌中调配时间与精力: 第二代理论强调行事历与日程表,反映出时间管理已注意到规划未来的重要: 第三代理论正是目前流行的优先级观念.也就是依据 ...
- 网页title标题的闪动效果
通过网页title来提示用户有新消息这个功能很常见,比如现在的微博,还有一些邮箱,这个功能都很常见. 显示信息数: <input type="text" id="t ...
- 了不起的分支和循环03 - 零基础入门学习Python009
了不起的分支和循环03 让编程改变世界 Change the world by program while循环 说完了分支我们来说说循环,标准的while循环语法我们已经可以熟悉掌握了. 这里我们就简 ...
- [C入门 - 游戏编程系列] 贪吃蛇篇(五) - 蛇实现
因为已经写了食物的实现,所以我不知道到底是该先写世界的实现还是蛇的实现.因为世界就是一个窗口,可以立刻在世界中看到食物的样子,对于大多数人来说,如果写完代码立刻就能看到效果,那就再好不过了.可是,我最 ...
- SVN上传代码时代码失败
Description : You are not authorized to access the files in the repository.Suggestion : You might be ...
- Oracle多行记录合并处理
1:效果如下图所示: 表T1: CREATE TABLE T1 ( WEEKWORKID VARCHAR2(20) , DD VARCHAR2(20) ) 表T2 CREATE TABLE T2 ( ...
- SALT-API兼HALITE测试搞定
妈XX,真的搞了近一周的空闲时间. 最后才领悟. 其实,先按HALITE的套路弄好,然后直接SALT-API就OK了..因为HALITE就是SALT-API的封闭和替代嘛. 随便参考一个URL搞定HA ...
- LeetCode_Sum Root to Leaf Numbers
Given a binary tree containing digits from 0-9 only, each root-to-leaf path could represent a number ...