POJ-3450 Corporate Identity (KMP+后缀数组)
Description
Beside other services, ACM helps companies to clearly state their “corporate identity”, which includes company logo but also other signs, like trademarks. One of such companies is Internet Building Masters (IBM), which has recently asked ACM for a help with their new identity. IBM do not want to change their existing logos and trademarks completely, because their customers are used to the old ones. Therefore, ACM will only change existing trademarks instead of creating new ones.
After several other proposals, it was decided to take all existing trademarks and find the longest common sequence of letters that is contained in all of them. This sequence will be graphically emphasized to form a new logo. Then, the old trademarks may still be used while showing the new identity.
Your task is to find such a sequence.
Input
The input contains several tasks. Each task begins with a line containing a positive integer N, the number of trademarks (2 ≤ N ≤ 4000). The number is followed by N lines, each containing one trademark. Trademarks will be composed only from lowercase letters, the length of each trademark will be at least 1 and at most 200 characters.
After the last trademark, the next task begins. The last task is followed by a line containing zero.
Output
For each task, output a single line containing the longest string contained as a substring in all trademarks. If there are several strings of the same length, print the one that is lexicographically smallest. If there is no such non-empty string, output the words “IDENTITY LOST” instead.
Sample Input
3
aabbaabb
abbababb
bbbbbabb
2
xyz
abc
0
Sample Output
abb
IDENTITY LOST 题目大意:给多个字符串,找出最长的并且字典序最小的公共子串.
两种做法:
(1).使用KMP.每一个子串都是某个后缀的前缀.枚举最短字符串的每一个后缀suff(i),让其他所有的字符串去跟suff(i)做kmp匹配,会得到一个suff(i)的公共前缀pre_suff(i),选一个最长的pre_suff
即为答案.枚举后缀时按照字典序枚举,可以省略掉比较长度相同的pre_suff这一过程.
(2).使用后缀数组.首先将所有的字符串连接成一条长串,求出height数组之后,二分枚举最长公共子串的长度mid,然后根据height值是否不小于mid将数组分成若干个连续的区间.查看每一个区
间,只要某个区间中的前缀来自所有的字符串,那么存在长度为mid的公共子串.但是我一直TLE. 代码如下(第一种做法):
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int N=4005; int SA[205];
int tSA[205];
int rk[205];
int cnt[205]; bool isSame(int *y,int i,int j,int k,int n)
{
if(y[i]!=y[j]) return false;
if(i+k<n&&j+k>=n) return false;
if(i+k>=n&&j+k<n) return false;
return y[i+k]==y[j+k];
} void buildSA(char* str,int n)
{
int *x=rk;
int *y=tSA;
int m=26;
for(int i=0;i<m;++i) cnt[i]=0;
for(int i=0;i<n;++i) ++cnt[x[i]=(str[i]-'a')];
for(int i=1;i<m;++i) cnt[i]+=cnt[i-1];
for(int i=n-1;i>=0;--i) SA[--cnt[x[i]]]=i; for(int k=1;k<=n;k<<=1){
int p=0;
for(int i=n-k;i<n;++i) y[p++]=i;
for(int i=0;i<n;++i) if(SA[i]>=k) y[p++]=SA[i]-k; for(int i=0;i<m;++i) cnt[i]=0;
for(int i=0;i<n;++i) ++cnt[x[y[i]]];
for(int i=1;i<m;++i) cnt[i]+=cnt[i-1];
for(int i=n-1;i>=0;--i) SA[--cnt[x[y[i]]]]=y[i]; p=1;
swap(x,y);
x[SA[0]]=0;
for(int i=1;i<n;++i)
x[SA[i]]=isSame(y,SA[i],SA[i-1],k,n)?p-1:p++; if(p>=n) break;
m=p;
}
} char tdmks[N][205];
int nxt[205]; void getNext(char* str,int str_len)
{
nxt[0]=nxt[1]=0;
for(int i=1;i<str_len;++i){
int j=nxt[i];
while(j&&str[i]!=str[j]) j=nxt[j];
nxt[i+1]=(str[i]==str[j])?j+1:0;
}
} int match(char* str,int str_len,char* ptr)
{
int ptr_len=strlen(ptr);
int tempLen=0,k=0;
for(int i=0;i<ptr_len;++i){
while(k&&ptr[i]!=str[k]) k=nxt[k];
if(str[k]==ptr[i]){
++k;
tempLen=max(tempLen,k);
}
}
return tempLen;
} int getLongestPre(char* str,int str_len,int cnt_tdmks)
{
getNext(str,str_len);
int long_pre=N;
for(int i=0;i<cnt_tdmks;++i){
long_pre=min(match(str,str_len,tdmks[i]),long_pre);
}
return long_pre;
} int input(int cnt_tdmks)
{
int minLen=N,id_minLen;
for(int i=0;i<cnt_tdmks;++i){
scanf("%s",tdmks[i]);
if(strlen(tdmks[i])<minLen){
minLen=strlen(tdmks[i]);
id_minLen=i;
}
}
return id_minLen;
} void solve(int p,int cnt_tdmks)
{
int m=strlen(tdmks[p]);
buildSA(tdmks[p],m);
int ans_len=0,ans_p;
for(int i=0;i<m;++i){
int len=getLongestPre(tdmks[p]+SA[i],m-SA[i],cnt_tdmks);
if(len>ans_len){
ans_len=len;
ans_p=SA[i];
}
}
if(ans_len){
for(int i=0;i<ans_len;++i)
printf("%c",tdmks[p][ans_p+i]);
printf("\n");
}else{
printf("IDENTITY LOST\n");
}
} int main()
{
//freopen("in.txt","r",stdin);
int n;
while(scanf("%d",&n)&&n)
{
solve(input(n),n);
}
return 0;
}
POJ-3450 Corporate Identity (KMP+后缀数组)的更多相关文章
- POJ 3450 Corporate Identity kmp+最长公共子串
枚举长度最短的字符串的所有子串,再与其他串匹配. #include<cstdio> #include<cstring> #include<algorithm> #i ...
- POJ 3450 Corporate Identity KMP解决问题的方法
这个问题,需要一组字符串求最长公共子,其实灵活运用KMP高速寻求最长前缀. 请注意,意大利愿父亲:按照输出词典的顺序的规定. 另外要提醒的是:它也被用来KMP为了解决这个问题,但是很多人认为KMP使用 ...
- poj 3450 Corporate Identity
题目链接:http://poj.org/problem?id=3450 题目分类:后缀数组 题意:求n个串的最长公共字串(输出字串) //#include<bits/stdc++.h> # ...
- POJ3450 Corporate Identity 【后缀数组】
Corporate Identity Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 7662 Accepted: 264 ...
- [HDU2328]Corporate Identity(后缀数组)
传送门 求 n 个串的字典序最小的最长公共子串. 和 2 个串的处理方法差不多. 把 n 个串拼接在一起,中间连上一个没有出现过的字符防止匹配过界. 求出 height 数组后二分公共子串长度给后缀数 ...
- POJ 3450 Corporate Identity(KMP)
[题目链接] http://poj.org/problem?id=3450 [题目大意] 求k个字符串的最长公共子串,如果有多个答案,则输出字典序最小的. [题解] 我们对第一个串的每一个后缀和其余所 ...
- POJ 3450 Corporate Identity (KMP,求公共子串,方法很妙)
http://blog.sina.com.cn/s/blog_74e20d8901010pwp.html我采用的是方法三. 注意:当长度相同时,取字典序最小的. #include <iostre ...
- POJ 3450 Corporate Identity (KMP+暴搞)
题意: 给定N个字符串,寻找最长的公共字串,如果长度相同,则输出字典序最小的那个. 找其中一个字符串,枚举它的所有的字串,然后,逐个kmp比较.......相当暴力,可二分优化. #include & ...
- poj 3518 Corporate Identity 后缀数组->多字符串最长相同连续子串
题目链接 题意:输入N(2 <= N <= 4000)个长度不超过200的字符串,输出字典序最小的最长公共连续子串; 思路:将所有的字符串中间加上分隔符,注:分隔符只需要和输入的字符不同, ...
随机推荐
- 【Linux】Jenkins安装(二)
Jenkins介绍 Jenkins是基于Java开发的一种持续集成工具,用于监控持续重复的工作,功能包括: 1.持续的软件版本发布/测试项目. 2.监控外部调用执行的工作. 安装环境 操作系统:lin ...
- 利用airbase-ng建立Soft AP
利用airbase-ng建立Soft AP,再利用一些常见工具进行嗅探,或对抓包进行分析是出现比较早的一种MITM攻击方法.网上有很多关于手动实现的文章,也有一些自动实现脚本.这些脚本通常分两类,一类 ...
- 关于eric4和pyqt的入门学习(转)
在Eric4下用PyQt4编写Python的图形界面程序 转载请注明作者RunningOn 本文是PyQt4的入门教程.网上能搜到其它教程,但我觉得讲得不是很清楚,希望这篇文章对入门者更加有帮助. 先 ...
- CCF CSP 201403-1 相反数
题目链接:http://118.190.20.162/view.page?gpid=T10 问题描述 试题编号: 201403-1 试题名称: 相反数 时间限制: 1.0s 内存限制: 256.0MB ...
- Python母版使用
设定base.html为母版,母版是页面的公共部分,可以减少代码冗余: 母版中变化的部分用: {% block page-main % } <!--page-mains是自己起的名称--&g ...
- C++ STL标准容器插入删除算法的复杂度
1 vector内部实现: 数组 // 就是没有固定大小的数组,vector直接翻译是向量的意思支持操作:begin(), //取首个元素,返回一个iteratorend(), //取末尾(最后一个元 ...
- Java基础面试题总结
目录 索引 Java基础知识篇 Java web基础知识总结 Java集合篇常见问题 Java基础知识篇 面向对象和面向过程的区别 面向过程: 优点:性能比面向对象高,因为类调用时需要实例化,开销比较 ...
- C 语言多线程与锁机制
C 语言多线程与锁机制 多线程 #include <pthread.h> void *TrainModelThread(void *id) { ... pthread_exit(NULL) ...
- BZOJ5279: [Usaco2018 Open]Disruption
题目大意:给你一棵n个节点的树,这n条边称为原边,另给出m条带权值的额外边,求删去每条原边后通过给出的m额外条边变回一棵树的最小价值.题解:看完题面以为是Tarjan连通性之类的题目,冷静分析后想到是 ...
- @Autowired注入报错
在用 @Autowired 注入多个类时,出现的错误 因为@Autowired 是按照类型注入,当找不到对应类型类时,才会去按照名称去找. 这时添加注解@Qualifier(“service”), ...