POJ2774Long Long Message (后缀数组&后缀自动机)
问题:
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
题意:
求两个字符串的最长的公共字串。
思路:
后缀自动机:可以直接匹配,然后又默写了一遍后缀自动机。
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=;
char chr[maxn],str[maxn];
struct SAM
{
int ch[maxn][],fa[maxn],maxlen[maxn],Last,sz;
void init()
{
sz=Last=; fa[]=maxlen[]=;
memset(ch[],,sizeof(ch[]));
}
void add(int x)
{
int np=++sz,p=Last;Last=np;
memset(ch[np],,sizeof(ch[np]));
maxlen[np]=maxlen[p]+;
while(p&&!ch[p][x]) ch[p][x]=np,p=fa[p];
if(!p) fa[np]=;
else {
int q=ch[p][x];
if(maxlen[p]+==maxlen[q]) fa[np]=q;
else {
int nq=++sz;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
maxlen[nq]=maxlen[p]+;
fa[nq]=fa[q];
fa[q]=fa[np]=nq;
while(p&&ch[p][x]==q) ch[p][x]=nq,p=fa[p];
}
}
}
void solve()
{
scanf("%s",chr);
int L=strlen(chr),x,tmp=,ans=;Last=;
for(int i=;i<L;i++){
x=chr[i]-'a';
if(ch[Last][x]) tmp++,Last=ch[Last][x];
else {
while(Last&&!ch[Last][x]) Last=fa[Last];
if(!Last) tmp=,Last=;
else tmp=maxlen[Last]+,Last=ch[Last][x];
}
ans=max(ans,tmp);
}
printf("%d\n",ans);
}
};
SAM Sam;
int main()
{ int T,i,L;
while(~scanf("%s",chr)){
Sam.init();
L=strlen(chr);
for(i=;i<L;i++) Sam.add(chr[i]-'a');
Sam.solve();
}
return ;
}
后缀数组:需要把两个串连接起来,之间加一个特殊符号,用来保证得到的结果符合两个串来自不同的母串。
效率对比:
后缀自动机94ms,后缀数组782ms。这种基本题型我还是愿意写后缀自动机,不过练一练总是有好处的。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=;
char str1[maxn],str2[maxn];
int L,ch[maxn];
struct SA
{
int cntA[maxn],cntB[maxn],A[maxn],B[maxn];
int rank[maxn],sa[maxn],tsa[maxn],ht[maxn];
void sort()
{
for (int i = ; i < ; i ++) cntA[i] = ;
for (int i = ; i <= L; i ++) cntA[ch[i]] ++;
for (int i = ; i < ; i ++) cntA[i] += cntA[i - ];
for (int i = L; i; i --) sa[cntA[ch[i]] --] = i;
rank[sa[]] = ;
for (int i = ; i <= L; i ++){
rank[sa[i]] = rank[sa[i - ]];
if (ch[sa[i]] != ch[sa[i - ]]) rank[sa[i]] ++;
}
for (int l = ; rank[sa[L]] < L; l <<= ){
for (int i = ; i <= L; i ++) cntA[i] = ;
for (int i = ; i <= L; i ++) cntB[i] = ;
for ( int i = ; i <= L; i ++){
cntA[A[i] = rank[i]] ++;
cntB[B[i] = (i + l <= L) ? rank[i + l] : ] ++;
}
for (int i = ; i <= L; i ++) cntB[i] += cntB[i - ];
for (int i = L; i; i --) tsa[cntB[B[i]] --] = i;
for (int i = ; i <= L; i ++) cntA[i] += cntA[i - ];
for (int i = L; i; i --) sa[cntA[A[tsa[i]]] --] = tsa[i];
rank[sa[]] = ;
for (int i = ; i <= L; i ++){
rank[sa[i]] = rank[sa[i - ]];
if (A[sa[i]] != A[sa[i - ]] || B[sa[i]] != B[sa[i - ]]) rank[sa[i]] ++;
}
}
}
void getht()
{
for (int i = , j = ; i <= L; i ++){
if (j) j --;
while (ch[i + j] == ch[sa[rank[i] - ] + j]) j ++;
ht[rank[i]] = j;
}
}
};
SA Sa;
int main()
{
scanf("%s",str1+);
scanf("%s",str2+);
int L1=strlen(str1+);
int L2=strlen(str2+);
for(int i=;i<=L1;i++) ch[i]=str1[i]-'a'+1;
ch[L1+]=;
for(int i=;i<=L2;i++) ch[i+L1+]=str2[i]-'a'+1;
L=L1+L2+;
Sa.sort();
Sa.getht();
int ans=;
for(int i = ; i <= L; i++)
{
if((Sa.sa[i]<=L1)!=(Sa.sa[i-]<=L1))
ans = max(ans, Sa.ht[i]);
}
printf("%d\n",ans);
return ;
}
POJ2774Long Long Message (后缀数组&后缀自动机)的更多相关文章
- 字符串的模板 Manacher kmp ac自动机 后缀数组 后缀自动机
为何scanf("%s", str)不需要&运算 经常忘掉的字符串知识点,最好不加&,不加&最标准,指针如果像scanf里一样加&是错的,大概是未定 ...
- 【整理】如何选取后缀数组&&后缀自动机
后缀家族已知成员 后缀树 后缀数组 后缀自动机 后缀仙人掌 后缀预言 后缀Splay ? 后缀树是后缀数 ...
- loj6173 Samjia和矩阵(后缀数组/后缀自动机)
题目: https://loj.ac/problem/6173 分析: 考虑枚举宽度w,然后把宽度压位集中,将它们哈希 (这是w=2的时候) 然后可以写一下string=“ac#bc” 然后就是求这个 ...
- POJ - 2774 Long Long Message (后缀数组/后缀自动机模板题)
后缀数组: #include<cstdio> #include<algorithm> #include<cstring> #include<vector> ...
- bzoj 3172 后缀数组|AC自动机
后缀数组或者AC自动机都可以,模板题. /************************************************************** Problem: 3172 Us ...
- [Luogu5161]WD与数列(后缀数组/后缀自动机+线段树合并)
https://blog.csdn.net/WAautomaton/article/details/85057257 解法一:后缀数组 显然将原数组差分后答案就是所有不相交不相邻重复子串个数+n*(n ...
- SPOJ694 DISUBSTR --- 后缀数组 / 后缀自动机
SPOJ694 DISUBSTR 题目描述: Given a string, we need to find the total number of its distinct substrings. ...
- POJ1743 Musical Theme (后缀数组 & 后缀自动机)最大不重叠相似子串
A musical melody is represented as a sequence of N (1<=N<=20000)notes that are integers in the ...
- SPOJ- Distinct Substrings(后缀数组&后缀自动机)
Given a string, we need to find the total number of its distinct substrings. Input T- number of test ...
随机推荐
- centos7.0 tomcat9.0 ip访问 manager
版本:Tomcat 9.0 问题:新安装的tomcat,用其他机器访问tomcat的Server Status.Manager App.Host Manager三个页面均显示403(本机访问没有问题) ...
- 使用Zxing.net实现asp.net mvc二维码功能
新建一个html辅助类 public static class HtmlHelperExtensions { , , ) { var barcodeWriter = new BarcodeWriter ...
- jQuery.callbacks 注释
(function( jQuery ) { // String to Object flags format cache var flagsCache = {}; // Convert String- ...
- Netty实现java多线程Post请求解析(Map参数类型)—SKY
netty解析Post的键值对 解析时必须加上一个方法,ch.pipeline().addLast(new HttpObjectAggregator(2048)); 放在自己的Handel前面. ht ...
- Linux安装Nginx使用负载均衡
1.实验准备准备三台计算机 nginx1 192.168.13.121 作为nginx负载均衡器nginx2 192.168.13.24 web服务,提供一个页面 nginx3 192 ...
- Android系统移植与调试之------->如何修改Android默认字体大小和设置里面字体大小比例
因为我修改 ro.sf.lcd_density的值,将它从160修改 为120,所以导致整个系统的字体都变得很小.因此需要将整个字体变大,并且在设置-->显示-->字体大小的4个选项的值都 ...
- spring data jpa 利用@Query进行查询
参照https://blog.csdn.net/yingxiake/article/details/51016234#reply https://blog.csdn.net/choushi300/ar ...
- java面向对象入门之带参方法创建
/* Name :创建带参的方法 Power by :Stuart Date:2015.4.25 */ //创建Way类 class Way{ //Way类成员的基本变量 int add1=123; ...
- java基础入门1到100的奇数求和
/* Name:1-100所有奇数求和的程序 Power by Stuart Date:2015-4-23 */ public class DateTest01{ public static void ...
- activiti--6-------------------------------------连线(一般数据库表的查询顺序)
一.流程图 二.这次把流程图和Java类放在一个包下 三.代码 package com.xingshang.f_sequenceFlow; import java.io.InputStream; im ...