POJ 3294 出现在至少K个字符串中的子串
在掌握POJ 2774(两个串求最长公共子串)以及对Height数组分组后,本题还是容易想出思路的。
首先用字符集外的不同字符连接所有串,这是为了防止两个后缀在比较时超过某个字符串的分界。二分子串的长度,扫描height数组,判定是否有某个分组来源与至少K个原字符串(本题要求出现超过n的一半次)。
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <string.h>
#include <stdio.h>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <cassert>
#include <sstream>
using namespace std; const int N=2e6+; int sa[N];
int t1[N],t2[N],c[N];
int rk[N],height[N]; inline int cmp(int *r,int a,int b,int l){
return r[a]==r[b]&&r[a+l]==r[b+l];
}
char s[N];
void calcSA (char *s,int n,int m) {
int i,j,p,*x=t1,*y=t2;
for(i=;i<m;i++)c[i]=;
for(i=;i<n;i++)c[x[i]=s[i]]++;
for(i=;i<m;i++)c[i]+=c[i-];
for(i=n-;i>=;i--)sa[--c[x[i]]]=i;
for(j=;j<=n;j<<=){
p=;
for(i=n-j;i<n;i++)y[p++]=i;
for(i=;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j; // 排名从小到大,如果pos比j大,则suffix(sa[i]-j)的第二关键字为p
for(i=;i<m;i++)c[i]=;
for(i=;i<n;i++)c[x[y[i]]]++;
for(i=;i<m;i++)c[i]+=c[i-];
for(i=n-;i>=;i--)sa[--c[x[y[i]]]]=y[i]; // 根据第二关键字从大到小,确定新一轮sa
swap(x,y);
p=;x[sa[]]=;
for(i=;i<n;i++)
x[sa[i]]=cmp(y,sa[i-],sa[i],j)?p-:p++;
if(p>=n)break;
m=p;
}
} void calcHeight(char *s,int n) {
int i,j,k=;
for(i=;i<=n;i++)rk[sa[i]]=i;
for(i=;i<n;i++){
if(k)k--; // h[i]>=h[i-1]-1
j=sa[rk[i]-]; // suffix(j)排名在suffix(i)前一位
while(s[i+k]==s[j+k])k++; // 暴力计算lcp
height[rk[i]]=k;
}
} int belong[N]; vector<int>ans;
bool vis[];
bool ok(int n,int m,int k) {
memset(vis,,sizeof vis);
int cnt=;
vis[belong[sa[]]]=true;
vector<int>ret;
bool push=false;
for (int i=;i<=n;i++) {
if (height[i]<m) {
memset(vis,,sizeof vis);
push=false;
vis[belong[sa[i]]]=true;
cnt=;
}
else if (!push){
if (!vis[belong[sa[i]]]) {
vis[belong[sa[i]]]=true;
++cnt;
}
if (cnt>k/&&!push) {
push=true;
ret.push_back(sa[i]);
}
}
}
//cout<<"go "<<m<<" "<<ret.size()<<endl;
if (ret.size()>) {
ans=ret;
return true;
}
else return false;
}
int main () {
int n;
while (scanf("%d",&n)!=EOF,n) {
int p=;
int maxLen=;
for (int i=;i<=n;i++) {
scanf("%s",s+p);
int l=strlen(s+p);
maxLen=max(maxLen,l);
int np=p+l;
for (int j=p;j<np;j++) {
belong[j]=i;
s[j]+=; // 这里+5是为了保证插入的分隔符不在字符集中出现,n至多为100,a的ASCII为97
}
belong[np]=;
p=np;
s[p++]=i;
}
s[--p]=;
belong[p]=-;
calcSA(s,p+,);
calcHeight(s,p);
int l=,r=maxLen,ret=;
while (l<=r) {
int m=(l+r)>>;
if (ok(p,m,n)) {
ret=m;
l=m+;
}
else
r=m-;
}
if (ret==) {
puts("?\n");
}
else {
for (int i=;i<ans.size();i++) {
int beg=ans[i];
for (int j=;j<ret;j++) printf("%c",s[beg+j]-);
puts("");
}
puts("");
}
}
return ;
}
POJ 3294 出现在至少K个字符串中的子串的更多相关文章
- Life Forms POJ - 3294(不小于k个字符串中的最长子串)
题意: 求不小于字符串一半长度个字符串中的最长字串 解析: 论文题例11 将n个字符串连起来,中间用不相同的且没有出现在字符串中的字符隔开, 求后缀数组, 然后二分答案变为判定性问题, 然后判断每组的 ...
- POJ 3294 Life Forms 后缀数组+二分 求至少k个字符串中包含的最长子串
Life Forms Description You may have wondered why most extraterrestrial life forms resemble humans, ...
- POJ-3294-Life Forms(后缀数组-不小于 k 个字符串中的最长子串)
题意: 给定 n 个字符串,求出现在不小于 k 个字符串中的最长子串. 分析: 将 n 个字符串连起来,中间用不相同的且没有出现在字符串中的字符隔开,求后缀数组. 然后二分答案,将后缀分成若干组,判断 ...
- PAT 字符串-02 删除字符串中的子串
/* 2 *PAT 字符串-02 删除字符串中的子串 3 *2015-08-09 4 作者:flx413 5 */ #include<stdio.h> #include<string ...
- 【JavaScript使用技巧】三个截取字符串中的子串,你用的哪个
[JavaScript使用技巧]三个截取字符串中的子串,你用的哪个 博客说明 文章所涉及的资料来自互联网整理和个人总结,意在于个人学习和经验汇总,如有什么地方侵权,请联系本人删除,谢谢! slice( ...
- 《Python CookBook2》 第一章 文本 - 替换字符串中的子串
替换字符串中的子串 任务: 给定一个字符串,通过查询一个字符串替换字典,将字符串中被标记的子字符串替换掉. 解决方案: >>> import string >>> ...
- C++ 在字符串中插入子串+推断字符串是否由空格组成
// Example3.cpp : 定义控制台应用程序的入口点. #include "StdAfx.h" #include <string> #include < ...
- poj 3294 后缀数组 多字符串中不小于 k 个字符串中的最长子串
Life Forms Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 16223 Accepted: 4763 Descr ...
- POJ 3261 可重叠的 k 次最长重复子串【后缀数组】
这也是一道例题 给定一个字符串,求至少出现 k 次的最长重复子串,这 k 个子串可以重叠.算法分析:这题的做法和上一题差不多,也是先二分答案,然后将后缀分成若干组.不同的是,这里要判断的是有没有一个组 ...
随机推荐
- AlloyFinger.js 源码 学习笔记及原理说明
此手势库利用了手机端touchstart, touchmove, touchend, touchcancel原生事件模拟出了 rotate touchStart multipointStart ...
- python实现视频下载
最近一两年短视频业务风生水起,各个视频网站都有各自特色的短视频内容.如果有这样一个程序,可以把各大视频网站的热门用户最新发布的视频都下载下来,不仅方便自己观看,还可以将没有版权的视频发布在个人社交网站 ...
- idea中编译项目报错 java: javacTask: 源版本 1.8 需要目标版本 1.8
问题如上面所叙: > idea中编译项目报错 java: javacTask: 源版本 1.8 需要目标版本 1.8 解决方案: > Setting->Compiler->Ja ...
- jeesite学习(一) common部分(1)
我们按照先细节后整体的方式来进行学习,即先了解各个包中包含的内容,再从整体上看各个包之间的关系. 0 common中的包 先看jeesite的common组件,common中共包含14个包(如下图), ...
- ng-class 用法
很长时间不写页面很多angualrjs的指令用法忘了,搜搜网上的千篇一律“不全”: 下面我把ngclass的用法列出来!(注:网上只有2种,我补充一种三维运算) 1: ng-class=" ...
- 使用Hibernate中出现了Caused by: java.sql.SQLException: Field 'gid' doesn't have a default value
那是因为表中没有设置主键自动增长,只需要改变表中的主键设置为自动增长即可
- mac压缩文件乱码
http://blog.b3inside.com/apple/solve-file-name-garbled-with-betterzip/
- iwebshop上传类的使用
$upload = new IUpload('10240000',array('jpg','gif','png')); $dir = "upload/dian"; $upload- ...
- Java 异常处理 try catch finally throws throw 的使用和解读(一)
//最近的一个内部表决系统开发过程中,//发现对异常处理还存在一些模棱两可的地方,//所以想着整理一下//主要涉及到://1.try catch finally throws throw 的使用和解读 ...
- 关于View Link
当需要表格之间的父子结构的时候需要展示时,这个时候就需要建立View Link来实现Table之间的关联.在建立ViewLink时需要现将JDev关闭然后再进行创建自己需要的ViewLink.