TZOJ3043: 取个标题好难 最长的出现次数>=k的不重复子串长度
3043: 取个标题好难 
Total Submit: 17 Accepted:4
Description
你是否经常在写完文章之后为文章取一个合适的标题而苦恼?这里提供一个很有趣的方法。
首先,标题应该概括文章的内容。为了简单起见,如果一个短语在文章中不重叠地出现了至少k次,那么这个短语就可以作为标题。例如,”dadadad”中,短语”dad” 不重叠地出现了两次,而不是三次。
其次,标题越长越好。长标题才能吸引眼球。
最后,这件事应该让计算机来做比较省事。
所以,请编写一个程序,根据给定的k和一段文章,给这篇文章取个标题。
Input
输入包括多组数据。
每组数据第一行为整数k,第二行为一个字符串表示文章内容,为了简化问题,字符串仅含小写字母。字符串长度不超过10000。
输入数据以k=0结束。
Output
对每组数据输出最长的标题长度,如果找不到符合要求的标题,则输出0。
Sample Input
3
abababa
1
apple
4
abababa
5
abababa
0
Sample Output
2
5
1
0
最长的出现次数>=k的不重复子串长度,这个题目明显可以hash,然后在二分长度,排序的时候将位置也标记下,最后判断下就可以了
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ulint;
#define maxn 23333
const ulint x=;
int M;
char in[maxn];
ulint has[maxn];
int pos[maxn];
int id[maxn];
ulint xp[maxn];
ulint H[maxn];
bool cmp(int a,int b)
{
return has[a]<has[b]||has[a]==has[b]&&a<b;
}
bool check(int mid,int n)
{
pos[mid]=;
id[]=;
for(int i=; i+mid-<n; i++)//就算每一段的hash值
id[i]=i,has[i]=H[i]-H[i+mid]*xp[mid];
sort(id,id+n-mid+,cmp);//按hash值排序
int cnt=;
bool ret=;
int tmp=id[];
for(int i=; i<=n-mid; i++)
if(has[id[i]]==has[id[i-]])
{
if(id[i]-tmp>=mid)
cnt++,tmp=id[i];
if(cnt>=M)
pos[mid]=max(pos[mid],tmp),ret=;
}
else
cnt=,tmp=id[i];
return ret;
}
int main()
{
xp[]=;
for(int i=; i<maxn; i++)//预处理x次幂项
xp[i]=xp[i-]*x;
while(scanf("%d",&M),M)
{
scanf("%s",in);
int n=strlen(in);
if(M==)
{
printf("%d\n",n);
continue;
}
H[n]=;
for(int i=n-; i >= ; i--)//预处理H[i]=s[i]+s[i+1]*x+...+s[n]*x^(n-i)
H[i]=H[i+]*x+(in[i]-'a');
int L=,R=n,mid,len=;
while(L<=R)
{
mid=(L+R)>>;
if(check(mid,n))
{
len=mid;
L=mid+;
}
else
R=mid-;
}
if(len==)
printf("0\n");
else
printf("%d\n",len);
}
return ;
}
然后也可以后缀数组,我们之前那个题允许重复,直接判断height即可,这个题目要保存sa[i],然后排序判断是否重复
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <set>
#define dbg(x) std::cout<<#x<<" = "<< (x)<< "\n"
#define maxn 20005
int wa[maxn],wb[maxn],wv[maxn],ws[maxn],m;
int cmp(int *r,int a,int b,int l)
{
return r[a]==r[b]&&r[a+l]==r[b+l];
}
void getsa(int *r,int *sa,int n,int m)
{
int i,j,p,*x=wa,*y=wb,*t;
for(i=; i<m; i++) ws[i]=;
for(i=; i<n; i++) ws[x[i]=r[i]]++;
for(i=; i<m; i++) ws[i]+=ws[i-];
for(i=n-; i>=; i--) sa[--ws[x[i]]]=i;
for(j=,p=; p<n; j*=,m=p)
{
for(p=,i=n-j; i<n; i++) y[p++]=i;
for(i=; i<n; i++) if(sa[i]>=j) y[p++]=sa[i]-j;
for(i=; i<n; i++) wv[i]=x[y[i]];
for(i=; i<m; i++) ws[i]=;
for(i=; i<n; i++) ws[wv[i]]++;
for(i=; i<m; i++) ws[i]+=ws[i-];
for(i=n-; i>=; i--) sa[--ws[wv[i]]]=y[i];
for(t=x,x=y,y=t,p=,x[sa[]]=,i=; i<n; i++)
x[sa[i]]=cmp(y,sa[i-],sa[i],j)?p-:p++;
}
}
int rank[maxn],height[maxn];
void calheight(int *r,int *sa,int n)
{
int i,j,k=;
for(i=; i<=n; i++) rank[sa[i]]=i;
for(i=; i<n; height[rank[i++]]=k)
for(k?k--:,j=sa[rank[i]-]; r[i+k]==r[j+k]; k++);
}
int a[maxn];
int check(int *sa,int n,int k)
{
int i,cnt=;
a[]=sa[];
for(i=; i<=n; i++)
{
if(height[i]>=k)
{
a[cnt++]=sa[i];
}
else
{
if(cnt>=m)
{
std::sort(a,a+cnt);
int x=a[],tot=cnt;
for(int i=; i<tot; i++)
{
if(a[i]-x<k)cnt--;
else x=a[i];
}
if(cnt>=m)return ;
}
cnt=,a[]=sa[i];
}
}
std::sort(a,a+cnt);
int x=a[],tot=cnt;
for(int i=; i<tot; i++)
{
if(a[i]-x<k)cnt--;
else x=a[i];
}
if(cnt>=m)return ;
return ;
}
int r[maxn],sa[maxn];
char str[maxn];
int main()
{
//freopen("test.in","r",stdin);
while(scanf("%d",&m),m)
{
scanf("%s",str);
int n=strlen(str);
if(m==)
{
printf("%d\n",n);
continue;
}
for(int i=; i<n; i++)r[i]=str[i];
r[n]=;
getsa(r,sa,n+,);
calheight(r,sa,n);
int L=,R=n,mi,len=;
while(L<=R)
{
mi=(L+R)>>;
if(check(sa,n,mi))L=mi+,len=mi;
else R=mi-;
}
printf("%d\n",len);
}
return ;
}
TZOJ3043: 取个标题好难 最长的出现次数>=k的不重复子串长度的更多相关文章
- Poj 1743——Musical Theme——————【后缀数组,求最长不重叠重复子串长度】
Musical Theme Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 22499 Accepted: 7679 De ...
- 最长不重复子串长度,时间复杂度O(n),空间复杂度O(n),Python实现
def lengthOfLongestSubstring(s): res = 0 d = {} tmp = 0 start = 0 for i in range(len(s)): if s[i] in ...
- LeetCode:Longest Substring Without Repeating Characters(最长不重复子串)
题目链接 Given a string, find the length of the longest substring without repeating characters. For exam ...
- POJ 3261 Milk Patterns 可重复k次的最长重复子串
Milk PatternsTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://poj.org/problem?id=3261 Description ...
- Longest Substring Without Repeating Characters 最长不重复子串
只遍历一次字符串即可求出最长不重复子串的长度. int lengthOfLongestSubstring(string s) { vector<,-); //记录字符上一次出现的位置,ASCII ...
- poj 1743 男人八题之后缀数组求最长不可重叠最长重复子串
Musical Theme Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 14874 Accepted: 5118 De ...
- [Jobdu] 题目1530:最长不重复子串
题目描述: 最长不重复子串就是从一个字符串中找到一个连续子串,该子串中任何两个字符都不能相同,且该子串的长度是最大的. 输入: 输入包含多个测试用例,每组测试用例输入一行由小写英文字符a,b,c... ...
- 【poj1743-Musical Theme】不可重叠最长重复子串-后缀数组
http://poj.org/problem?id=1743 这题是一道后缀数组的经典例题:求不可重叠最长重复子串. 题意: 有N(1 <= N <=20000)个音符的序列来表示一首乐曲 ...
- 九度oj 题目1530:最长不重复子串
题目描述: 最长不重复子串就是从一个字符串中找到一个连续子串,该子串中任何两个字符都不能相同,且该子串的长度是最大的. 输入: 输入包含多个测试用例,每组测试用例输入一行由小写英文字符a,b,c... ...
随机推荐
- frcnn_train_data_param的distort_param实现
frcnn_train_data_param frcnn_train_data_param { source: "./data/train_list.txt" root_folde ...
- 剑指offer 和为s的两个数字的调试
这是整个调试, for (int i:s) cout<<i<<endl;这句话是c++11特性下的一种遍历方式 在编译的时候需要加-std=c++11,即g++ 41.cpp ...
- 移动端定制软键盘样式 配置input属性的type属性
1.当你的input输入的数据为链接地址时type属性可改为 type=url 最下面一栏就会出现.com 提高用户体验 2.当你的input输入的数据为email时type属性可改为 type=em ...
- mysql 全连接 报错1051的原因
由于mysql 不支持 直接写full outer join 或者 full join来表示全外连接但是可以用left right union right 代替 下面是例子: select * fro ...
- js图片库 案例
事件处理函数:事件处理函数的作用是,在特定事件发生时调用特定的JavaScript代码.本例中想要在用户点击某个链接的时候触发一个动作,所以需要使用onclick事件处理函数. 添加事件处理函数的语法 ...
- HTML中行内元素和块级元素的区别及转换
区别可以去找 “html文档流”相关的资料去学习,最主要的区别就是元素是占据一行还是挤在一行 转换的方式是用css的display属性 display:block; /*转换为块级*/display: ...
- 循环语句:LOOP,WHILE和数字式循环
一 简单循环 1 语法: LOOP 要执行的语句; EXIT WHEN <条件语句> --条件满足,退出循环语句 END LOOP; 2 例子: DECLARE ...
- C++声明之CV限定符
目录 1.const 1.1 const obj 如果调用 non-const member fun会编译出错 经典错误 1.2 例子:STD里的操作符重载 1.3 例子:<cpp primer ...
- spring-开发需要jar包
需要的开发包 Spring核心开发包: Commons-logging.jar Spring-beans.jar Spring-context.jar Spring-core.jar Spring-e ...
- tcl之控制流-break/continue