POJ-3693/HDU-2459 Maximum repetition substring 最多重复次数的子串(需要输出具体子串,按字典序)
http://acm.hdu.edu.cn/showproblem.php?pid=2459
之前hihocoder那题可以算出最多重复次数,但是没有输出子串。一开始以为只要基于那个,每次更新答案的时候按SA更新子串起始位置和长度就好了,但实际发现那个解法在计算重复次数的时候并不会遍历每一个合法串(比如daeaea,枚举长度为2时,只会计算eaea,漏了aeae)所以不能直接在计算过程中直接得出答案。
那难道又要退化成枚举每个起始位置了么?其实不然,我们可以记录答案支持的所有长度(这个数组不会太大),扫描SA,每个SA都枚举长度,一旦发现满足直接输出并结束,另外特判一下只出现一次的重复串(即ascii最小的单字符)。
#include <cstdio>
#include <string>
#include <iostream>
#include <set>
#include <algorithm>
#include <vector>
#include <map>
#include <cstring>
#include <queue>
#include <cmath>
#define LL int
using namespace std;
const LL N = ;
string s;
int lx[N];
class SF
{
//N:数组大小
public:
int x[N], y[N], c[N];
int Height[N], str[N], SA[N], Rank[N];//Height数组从2开始,SA记录Rank=i的下标
int slen;
int m;//字符集处理大小(传入如果不是数字,需要做位移转换)
bool cmp(int* r, int a, int b, int l)
{
return r[a] == r[b] && r[a + l] == r[b + l];
}
void Suffix(int n)
{
++n;
int i, j, p;
for (i = ; i < m; ++i) c[i] = ;
for (i = ; i < n; ++i) c[x[i] = str[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;
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]; 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;
} int k = ;
n--;
for (i = ; i <= n; ++i) Rank[SA[i]] = i;
for (i = ; i < n; ++i)
{
if (k)--k;
j = SA[Rank[i] - ];
while (str[i + k] == str[j + k])++k;
Height[Rank[i]] = k;
//cout << k << endl;
}
}
static const int bitlen = ;
LL lg2(LL p)//计算log2(n)
{
return (LL)(log(p) / log());
}
LL dp[bitlen][N];
LL bit[bitlen];
void initRMQ()//初始化
{
bit[] = ;
for (int i = ; i < bitlen; i++) bit[i] = * bit[i - ];
for (int i = ; i <= slen; i++)
dp[][i] = Height[i];
dp[][] = dp[][] = ;
for (LL i = ; bit[i] < slen + ; i++)
for (LL j = ; j + bit[i] <= slen + ; j++)
dp[i][j] = min(dp[i - ][j], dp[i - ][j + bit[i - ]]);
}
LL query(LL l, LL r)//查询两个Rank之间的lcp
{
if (r == l) return slen - SA[l];
if (l > r) swap(l, r);
l++;
LL mig = lg2(r - l + 1.0);
return min(dp[mig][l], dp[mig][r - bit[mig] + ]);
}
void init(string &s)
{
m=;
slen = s.size();
for (int i = ; i < slen; i++)
str[i] = s[i] - 'a' + ;//如果是字符,映射成从1开始的序列
str[slen] = ;//1作为结束符,防止越界
Suffix(slen);
initRMQ();
}
void solve()//cascnacnacdsdaj
{
int ans = ,al,st=-;
int cnt=;
set<char>fuck;
for(int i=; i<slen; i++)
fuck.insert(s[i]);
for (int len = ; len <= slen; len++)
{
for (int i = ; i+len< slen; i+=len)
{
int r1 = Rank[i], r2 = Rank[i+ len];
int lcp = query(r1, r2);
int sta=i;
if(ans<=lcp / len + )
{
if(ans<lcp / len + )
{
cnt=;
lx[cnt++]=len;
}
else lx[cnt++]=len;
ans=lcp / len + ;
} if (i - len + lcp%len >= )
{
sta=i - len + lcp%len;
if(sta==i-len)sta++;
lcp = query(Rank[sta], Rank[sta+len]);
if(ans<=lcp / len + )
{
if(ans<lcp / len + )
{
cnt=;
lx[cnt++]=len;
}
else lx[cnt++]=len;
ans=lcp / len + ;
}
}
}
}
int pos=-,lxl;
for(int i=; i<=slen; i++)
{
for(int j=;j<cnt;j++)
{
int sta=SA[i];
if(sta+lx[j]>=slen)break;
int rk=Rank[sta+lx[j]];
int lcp = query(i, rk);
if(ans==lcp / lx[j] + )
{
for(int i=; i<ans*lx[j]; i++)
cout<<s[i+sta];
cout<<endl;
goto li;
}
}
}
cout<<*fuck.begin()<<endl;
return;
li:
; }
} sf;
int main()
{
cin.sync_with_stdio(false);
//freopen("in.txt","r",stdin);
//freopen("o1.txt","w",stdout);
int cas=;
while (cin >> s)
{
if(s=="#")break;
cout<<"Case "<<cas++<<": ";
sf.init(s);
sf.solve();
}
return ;
}
POJ-3693/HDU-2459 Maximum repetition substring 最多重复次数的子串(需要输出具体子串,按字典序)的更多相关文章
- HDU 2459 Maximum repetition substring
题目:Maximum repetition substring 链接:http://acm.hdu.edu.cn/showproblem.php?pid=2459 题意:给你一个字符串,求连续重复出现 ...
- POJ - 3693 Maximum repetition substring(重复次数最多的连续重复子串)
传送门:POJ - 3693 题意:给你一个字符串,求重复次数最多的连续重复子串,如果有一样的,取字典序小的字符串. 题解: 比较容易理解的部分就是枚举长度为L,然后看长度为L的字符串最多连续出现 ...
- POJ 3693 (后缀数组) Maximum repetition substring
找重复次数最多的字串,如果有多解,要求字典序最小. 我也是跟着罗穗骞菊苣的论文才刷这道题的. 首先还是枚举一个循环节的长度L,如果它出现两次的话,一定会包含s[0], s[L], s[2L]这些相邻两 ...
- 【HDOJ】2459 Maximum repetition substring
后缀数组+RMQ. /* 2459 */ #include <iostream> #include <sstream> #include <string> #inc ...
- POJ 3693 Maximum repetition substring(最多重复次数的子串)
Maximum repetition substring Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 10461 Ac ...
- 【POJ 3693】Maximum repetition substring 重复次数最多的连续重复子串
后缀数组的论文里的例题,论文里的题解并没有看懂,,, 求一个重复次数最多的连续重复子串,又因为要找最靠前的,所以扫的时候记录最大的重复次数为$ans$,扫完后再后从头暴力扫到尾找重复次数为$ans$的 ...
- POJ 3693 Maximum repetition substring(后缀数组)
Description The repetition number of a string is defined as the maximum number R such that the strin ...
- poj 3693 Maximum repetition substring (后缀数组)
其实是论文题.. 题意:求一个字符串中,能由单位串repeat得到的子串中,单位串重复次数最多的子串.若有多个重复次数相同的,输出字典序最小的那个. 解题思路:其实跟论文差不多,我看了很久没看懂,后来 ...
- POJ3693 Maximum repetition substring —— 后缀数组 重复次数最多的连续重复子串
题目链接:https://vjudge.net/problem/POJ-3693 Maximum repetition substring Time Limit: 1000MS Memory Li ...
随机推荐
- topcoder srm 305 div1
problem1 link 直接按照题意模拟即可. import java.util.*; import java.math.*; import static java.lang.Math.*; pu ...
- Spring 学习——Spring框架结构、概念
maven项目结构 记忆:在一个项目中,project下一层级时src,也就是源文件,所有需要进行编译的文件都是在这个目录下,其实也就是这一个目录,然后向下扩展.在src目录下,存在main文件夹,里 ...
- uniGUI试用笔记(三)
uniGUI下的MessageDlg使用发生了变化,最大的特点是: 1.成为了uniGUIForm的成员函数: 2.变成过程(procedure)了,也就是没有返回值了,使得程序不再具有线程阻塞性. ...
- Python3 tkinter基础 Canvas create_rectangle 画矩形
Python : 3.7.0 OS : Ubuntu 18.04.1 LTS IDE : PyCharm 2018.2.4 Conda ...
- sed 替换换行回车
A carriage return linefeed (CRLF) is a special sequence of characters, used by DOS/Windows, to signi ...
- P4363 [九省联考2018]一双木棋chess
思路 容易发现只能在轮廓线的拐点处落子,所以棋盘的状态可以用一个n+m长度的二进制数表示 转移就是10变成01 代码 #include <cstdio> #include <algo ...
- NIO小纪
我们通常说的NIO大多数场景下都是基于I/O复用技术的NIO,比如jdk中的NIO,当然Tomcat8以后的NIO也是指的基于I/O复用的NIO.注意,使用NIO != 高性能,当连接数<100 ...
- Java创建对象的几种方式。
Java创建对象的几种方式(重要): (1) 用new语句创建对象,这是最常见的创建对象的方法. (2) 运用反射手段,调用java.lang.Class或者java.lang.reflect.Con ...
- Git误操作 git reset强制回滚 恢复commit方法
参考: 找回Git中丢失的Commit Git误操作 git reset强制回滚 恢复commit方法 使用Git时,常有误操作,在Commit之后又执行了git reset --hard HEAD强 ...
- vim命令详解
VIM编辑常用技巧 vim编辑器 简介: vi: Visual Interface,文本编辑器 文本:ASCII, Unicode 文本编辑种类: 行编辑器: sed 全屏编辑器:nano, vi V ...