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
在字符串处理当中,后缀树和后缀数组都是非常有力的工具,其中后缀树大家了解得比较多,关于后缀数组则很少见于国内的资料.其实后缀是后缀树的一个非常精巧的替代品,它比后缀树容易编程实现,能够实现后缀树的很多 ...
随机推荐
- IFS解惑
一.IFS 介绍 Shell 脚本中有个变量叫 IFS(Internal Field Seprator) ,内部域分隔符.完整定义是The shell uses the value stored in ...
- hibernate多对多映射文件详解(一)
1.仓库表属性 public class WarehouseNew implements java.io.Serializable { // Fields private static final l ...
- 搬寝室(HDU 1421 DP)
搬寝室 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submiss ...
- 鼠标点击变色 lvha
a标签有四个"状态"的先后过程是:a:link ->a:hover ->a:active ->a:visited.另外,a:active不能设置有无下划线(总是有 ...
- 如何查看linux版本
1. 查看内核版本命令: 1) [root@q1test01 ~]# cat /proc/version Linux version 2.6.9-22.ELsmp (bhcompile@crowe ...
- PowerShell中的输出
1 输出重定向 > 或者>> 2 输出控制 out-* -paging#分页输出 get-process | out-host -paging more指令用于屏显 get-pro ...
- B/S 网站技术选型
Windows平台: http://www.asp.net, http://www.asp.net/mvc Web技术 http://msdn.microsoft.com/ef 数据访问中间件 htt ...
- Codeforces243C-Colorado Potato Beetle(离散化+bfs)
Old MacDonald has a farm and a large potato field, (1010 + 1) × (1010 + 1) square meters in size. Th ...
- hdu 1829 A Bug's Life(并查集)
A Bu ...
- c++在函数后面加const
非静态成员函数后面加const(加到非成员函数或静态成员后面会产生编译错误),表示成员函数隐含传入的this指针为const指针,决定了在该成员函数中,任意修改它所在的类的成员的操作都是不允许的(因为 ...