1.題面
2,題意
給定一個字符串和一個數字m, 要求找出最少出現m次的最長的字符串,這些字符串之間可以重疊
3.思路
使用字符串hash或是後綴數組
4.代碼
/*****************************************************************
> File Name: cpp_acm.cpp
> Author: Uncle_Sugar
> Mail: [email protected]
> Created Time: Sat 20 Aug 2016 23:14:46 CST
*****************************************************************/
# include <cstdio>
# include <cstring>
# include <cctype>
# include <cmath>
# include <cstdlib>
# include <climits>
# include <iostream>
# include <iomanip>
# include <set>
# include <map>
# include <vector>
# include <stack>
# include <queue>
# include <algorithm>
using namespace std;
# define rep(i,a,b) for (i=a;i<=b;i++)
# define rrep(i,a,b) for (i=b;i>=a;i--)
template<class T>void PrintArray(T* first,T* last,char delim=' '){
for (;first!=last;first++) cout << *first << (first+1==last?'\n':delim);
}
const int debug = 1;
const int size = 10 + 40000;
const int INF = INT_MAX>>1;
typedef unsigned long long ll;
const ll MOD = 1000000007;
/*
1.see the size of the input data before you select your algorithm
2.cin&cout is not recommended in ACM/ICPC
3.pay attention to the size you defined, for instance the size of edge is double the size of vertex
*/
ll Count[size];
char s[size];
int len = 0;
ll hhash[size];
void pretreat(){
hhash[0] = 0;
for (int i = 1; i <= len; i++){
hhash[i] = hhash[i-1] + (s[i-1] - 'a' + 1)*Count[i];
}
}
ll key[size];
int rrank[size];
bool cmp(int a, int b){
return key[a] < key[b];
}
int check(int m, int c){
for (int i = m; i <= len; i++){
rrank[i] = i;
key[i] = (hhash[i] - hhash[i - m])*Count[len-i];
}
sort(rrank + m, rrank + len + 1, cmp);
int cnt = 0, pos = 0;
int right_most = -1;
for (int i = m; i <= len; i++){
if (i==m||key[rrank[i]] != key[rrank[i-1]]) {
pos = rrank[i];
cnt = 1;
}else {
pos = max(rrank[i], pos);
cnt++;
}
if (cnt >= c) right_most = max(right_most, pos);
}
return right_most;
}
int main()
{
/*std::ios::sync_with_stdio(false);cin.tie(0);*/
Count[0] = 1;
for (int i = 1; i < size; i++) Count[i] = Count[i-1]*MOD;
int m;
while (scanf("%d",&m) != EOF){
if (!m) break;
scanf("%s", s);
len = strlen(s);
pretreat();
int l = 0, r = len + 1;
int anspos = 0;
while (l < r - 1){
int mid = l+r>>1;
int k = check(mid, m);
if (k != -1){
l = mid;
anspos = k;
}else {
r = mid;
}
}
if (l == 0)
printf("none\n");
else
printf("%d %d\n",l ,anspos-l);
}
return 0;
}