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 个子串可以重叠.算法分析:这题的做法和上一题差不多,也是先二分答案,然后将后缀分成若干组.不同的是,这里要判断的是有没有一个组 ...
 
随机推荐
- CoreGraphics--画线/圆/矩形
			
- (void)drawRect:(CGRect)rect { // Drawing code NSLog(@"drawRect自动调用"); //画图步骤 //获取上下文(/画笔 ...
 - 摆脱printf的噩梦
			
众所周知,printf是一个方便.直观.易写.变长参数的打印函数,但它有一个致命的缺陷,如下的语句将导致程序出现严重的运行时错误: printf("%s", 1); 然后程序中断, ...
 - Permanent Generation Removal Overview(译文)
			
英文原稿:http://vdisk.weibo.com/s/vxGdGZEZTEjk 中文整理稿:http://it.deepinmind.com/gc/2014/05/14/metaspace-in ...
 - idea调试SpringMvc, 出现:”通配符的匹配很全面, 但无法找到元素 'mvc:annotation-driven' 的声明“错误的解决方法
			
调试json格式输出,出现以下错误: HTTP Status 500 - Servlet.init() for servlet HelloDispatcher threw exception ty ...
 - 百度推送-sitemap-使用playframework框架实现-java
			
主动推送的目的是能够把我们高质量内容推送给百度,但是首先你得有一个属于你自己的网站,在百度站长进行验证通过之后,才有资格推送百度sitemap. 百度站长平台为未使用百度统计的站点提供三种验证方式:文 ...
 - JAVA基础知识(1)
			
1.JAVA的三大体系:JME(微缩版),JSE(标准版),JEE(企业版): 2.JAVA的三大核心机制:JAVA虚拟机,垃圾回收机制,代码安全性检测 3.java开发集JDK 4.java编译器j ...
 - spring学习——注入静态对象属性
			
spring注入静态对象属性时,因为虚拟机类加载问题,直接在属性上使用@Autowired 是不可以的.需要在属性对应的set方法上@Autowired,并且,set方法不能定义为static. 1. ...
 - iOS 上传文件
			
NSString *boundry = @"boundry";//分节符 NSMutableURLRequest *mutableRequest = [NSMutableURLRe ...
 - Java基础—JDK环境变量配置
			
1.安装JDK 下载网址:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 注意点 ...
 - 实现一个自己的promise
			
这是小弟的一篇开篇小作,如有不当之处,请各位道友批评指正.本文将探讨Promise的实现. 一.ES6中的Promise 1.简介 据说js很早就实现了Promise,我是不知道的,我第一次接触Pro ...