POJ 3261 字符串
来源:互联网 发布:济宁行知中学 编辑:程序博客网 时间:2024/05/18 01:46
题意:给定一个字符串,求最少出现K次的最长重复字串,这K个字串可以重叠。
做法:1.hash(二分最大长度,这里要判断的是枚举起点,然后对该长度的字串求hash值,统计下该字串出现了几次,如果>=k,则满足条件)
2.后缀数组(论文经典题,详细看论文)
code:
1.
#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#include <vector>#include <queue>#include <map>#include <set>#include <cmath>#include <string>#define zero(x) (((x)>0?(x):-(x))<eps)#define MAGIC 1121117#define eps 1e-8#define ULL unsigned long long#define Test puts("END")using namespace std;const int MOD = 1000000007;const int INF = 1000000000;const int N = 100005;const int M = 311117;int a[N],n,K,hash[N],fac[N];int times[M],value[M];bool used[M];void makeHash(){ hash[0] = a[0]; for(int i = 1;i < n;i ++){ hash[i] = hash[i - 1] * MAGIC + a[i]; }}int getPos(int v){ int pos = (v % M + M) % M; while(used[pos] && value[pos] != v){ pos ++; // cout << "pos " << pos << endl; if(pos >= M){ pos -= M; } } return pos;}int getHash(int l,int r){ if(l == 0) return hash[r]; else return hash[r] - hash[l - 1] * fac[r - l + 1];}int insert(int v){ int pos = getPos(v); if(!used[pos]){ used[pos] = true; value[pos] = v; } times[pos] ++; return times[pos];}bool check(int limit){ memset(times,0,sizeof(times)); memset(used,false,sizeof(used)); for(int l = 0;l + limit - 1 < n;l ++){ int r = l + limit - 1; int v = getHash(l,r); int ret = insert(v); if(ret >= K) return true; } return false;}int main(){ // freopen("input.txt","r",stdin); while(scanf("%d%d",&n,&K) != EOF){ for(int i = 0;i < n;i ++){ scanf("%d",&a[i]); } fac[0] = 1; for(int i = 1;i < N;i ++) fac[i] = fac[i - 1] * MAGIC; makeHash(); int l = 0,r = n; int ans = -1; while(l <= r){ int mid = (l + r) >> 1; // cout << l << ' ' << r << endl; if(check(mid)){ ans = mid; l = mid + 1; } else r = mid - 1; } printf("%d\n",ans); } return 0;}
2.后缀数组
#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#include <vector>#include <queue>#include <map>#include <set>#include <cmath>#include <string>#define zero(x) (((x)>0?(x):-(x))<eps)#define MAGIC 11117#define eps 1e-8#define LL long long#define Test puts("END")using namespace std;const int MOD = 1000000007;const int INF = 1000000000;const int N = 2000100;const int M = 2000100;int s[N],n,K;int wa[N],wb[N],wv[N],wc[N],rank[N],height[N],sa[N];void calheight(int *r,int *sa,int n){ int i,j,k = 0; for(i = 1;i <= n;i ++) rank[sa[i]] = i; for(i = 0;i < n;height[rank[i ++ ]] = k) for(k ? k -- : 0,j = sa[rank[i] - 1];r[i + k] == r[j + k];k ++); return ;}int cmp(int *r,int a,int b,int l){ return r[a] == r[b] && r[a + l] == r[b + l];}void da(int *r,int *sa,int n,int m){ int i,j,p,*x = wa,*y = wb,*t; for(i = 0;i < m;i ++) wc[i] = 0; for(i = 0;i < n;i ++) wc[x[i] = r[i]] ++; for(i = 1;i < m;i ++) wc[i] += wc[i - 1]; for(i = n - 1;i >= 0;i --) sa[-- wc[x[i]]] = i; for(j = 1,p = 1;p < n;j *= 2,m = p){ for(p = 0,i = n - j;i < n;i ++) y[p ++] = i; for(i = 0;i < n;i ++) if(sa[i] >= j) y[p ++] = sa[i] - j; for(i = 0;i < n;i ++) wv[i] = x[y[i]]; for(i = 0;i < m;i ++) wc[i] = 0; for(i = 0;i < n;i ++) wc[wv[i]] ++; for(i = 1;i < m;i ++) wc[i] += wc[i - 1]; for(i = n - 1;i >= 0;i --) sa[-- wc[wv[i]]] = y[i]; for(t = x,x = y,y = t,p = 1,x[sa[0]] = 0,i = 1;i < n;i ++) x[sa[i]] = cmp(y,sa[i - 1],sa[i],j) ? p - 1 : p ++; } return ;}bool check(int limit){ int l = 0; while(l <= n){ if(height[l] < limit){ l ++; continue; } int r = l; while(r <= n && height[r] >= limit){ r ++; } if(r - l + 1>= K) return true; l = r; } return false;}int main(){ // freopen("input.txt","r",stdin); while(scanf("%d%d",&n,&K) != EOF){ for(int i = 0;i < n;i ++){ scanf("%d",&s[i]); } da(s,sa,n + 1,200); calheight(s,sa,n); /*for(int i = 0;i <= n;i ++) printf("i:%d sa:%d height:%d\n",i,sa[i],height[i]);*/ // check(4); int l = 0,r = n; int ans = -1; while(l <= r){ int mid = (l + r) >> 1; // cout << l << ' ' << r << endl; if(check(mid)){ ans = mid; l = mid + 1; } else r = mid - 1; } printf("%d\n",ans); } return 0;}
- POJ 3261 字符串
- POJ 2159 字符串加密
- POJ 2803 字符串识别
- POJ-1002(字符串+排序)
- poj 1002 字符串
- POJ 1056 字符串
- POJ 1028 字符串
- poj字符串总结
- poj 1002 string字符串
- poj 1002 (字符串基础)
- POJ 2176 Folding (字符串)
- POJ 1200 字符串hash
- POJ 3981 字符串替换
- POJ 1035 字符串
- poj 2192 字符串匹配
- poj 3356 字符串编辑
- poj 3602-字符串模拟
- POJ 字符串对应
- 微信团队:微信公众平台重在连接用户和服务
- 开关二极管
- Java 访问修饰符
- WPF中的控件定位
- OpenGL超级宝典的例子Triangle
- POJ 3261 字符串
- eclipse下的java build path配置
- CentOS 6.0下vncserver安装配置
- 数据库与数据仓库的区别是什么
- C# .NET 获取路径信息
- JAVA语言为什么能跨平台?(转)
- 谷歌地图之地名解析
- HDU 4363 Draw and paint DP
- Java中的异常checkedException和uncheckedException