UVA 10526 - Intellectual Property (后缀数组)
UVA 10526 - Intellectual Property
题意:给定两个问题,要求找出第二个文本抄袭第一个文本的全部位置和长度,输出前k个,按长度从大到小先排。长度一样的按位置从小到大
思路:后缀数组,把两个文本拼接起来。记录下拼接位置为tdp。这样假设sa[i] < tdp就是前面的文本开头。假设sa[i] >= tdp就是后面的文本开头,拼接起来的求出height数组,利用该数组的性质。从前往后扫一遍,从后往前扫一遍。把全部位置的最大值保存下来。最后在扫描一遍位置。把答案记录下来
代码:
- #include <cstdio>
- #include <cstring>
- #include <algorithm>
- using namespace std;
- const int MAXLEN = 200005;
- const int INF = 0x3f3f3f3f;
- char str[55555];
- int k, tdp, an, v[MAXLEN];
- struct Ans {
- int len, pos;
- Ans() {}
- Ans(int len, int pos) {
- this->len = len;
- this->pos = pos;
- }
- } ans[MAXLEN];
- bool cmp(Ans a, Ans b) {
- if (a.len == b.len) return a.pos < b.pos;
- return a.len > b.len;
- }
- struct Suffix {
- int s[MAXLEN];
- int sa[MAXLEN], t[MAXLEN], t2[MAXLEN], c[MAXLEN], n;
- int rank[MAXLEN], height[MAXLEN];
- void build_sa(int m) {
- n++;
- int i, *x = t, *y = t2;
- for (i = 0; i < m; i++) c[i] = 0;
- for (i = 0; i < n; i++) c[x[i] = s[i]]++;
- for (i = 1; i < m; i++) c[i] += c[i - 1];
- for (i = n - 1; i >= 0; i--) sa[--c[x[i]]] = i;
- for (int k = 1; k <= n; k <<= 1) {
- int p = 0;
- for (i = n - k; i < n; i++) y[p++] = i;
- for (i = 0; i < n; i++) if (sa[i] >= k) y[p++] = sa[i] - k;
- for (i = 0; i < m; i++) c[i] = 0;
- for (i = 0; i < n; i++) c[x[y[i]]]++;
- for (i = 0; i < m; i++) c[i] += c[i - 1];
- for (i = n - 1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i];
- swap(x, y);
- p = 1; x[sa[0]] = 0;
- for (i = 1; i < n; i++)
- x[sa[i]] = (y[sa[i - 1]] == y[sa[i]] && y[sa[i - 1] + k] == y[sa[i] + k]) ? p - 1 : p++;
- if (p >= n) break;
- m = p;
- }
- n--;
- }
- void getHeight() {
- int i, j, k = 0;
- for (i = 1; i <= n; i++) rank[sa[i]] = i;
- for (i = 0; i < n; i++) {
- if (k) k--;
- int j = sa[rank[i] - 1];
- while (s[i + k] == s[j + k]) k++;
- height[rank[i]] = k;
- }
- }
- void init() {
- tdp = 0; n = 0; an = 0;
- gets(str);
- while (gets(str)) {
- if (strcmp(str, "END TDP CODEBASE") == 0) break;
- int len = strlen(str);
- str[len] = '\n';
- for (int i = 0; i <= len; i++)
- s[n++] = str[i];
- }
- tdp = n;
- s[n++] = 260;
- gets(str);
- while (gets(str)) {
- if (strcmp(str, "END JCN CODEBASE") == 0) break;
- int len = strlen(str);
- str[len] = '\n';
- for (int i = 0; i <= len; i++)
- s[n++] = str[i];
- }
- s[n] = 0;
- }
- void solve() {
- init();
- build_sa(261);
- getHeight();
- memset(v, 0, sizeof(v));
- int Min = -1;
- for (int i = 1; i <= n; i++) {
- if (sa[i] < tdp) Min = INF;
- else if (sa[i] > tdp) {
- if (Min == -1) continue;
- Min = min(height[i], Min);
- v[sa[i] - tdp - 1] = max(Min, v[sa[i] - tdp - 1]);
- }
- }
- Min = -1;
- for (int i = n; i >= 1; i--) {
- if (sa[i] < tdp) Min = INF;
- else if (sa[i] > tdp) {
- if (Min == -1) continue;
- Min = min(height[i + 1], Min);
- v[sa[i] - tdp - 1] = max(Min, v[sa[i] - tdp - 1]);
- }
- }
- int r = -1;
- for (int i = 0; i < n - tdp; i++) {
- if (i + v[i] <= r) continue;
- if (v[i] == 0) continue;
- ans[an++] = Ans(v[i], i);
- r = i + v[i];
- }
- sort(ans, ans + an, cmp);
- for (int i = 0; i < min(an, k); i++) {
- printf("INFRINGING SEGMENT %d LENGTH %d POSITION %d\n", i + 1, ans[i].len, ans[i].pos);
- for (int j = ans[i].pos + tdp + 1; j < ans[i].pos + tdp + 1 + ans[i].len; j++)
- printf("%c", s[j]);
- printf("\n");
- }
- }
- } gao;
- int main() {
- int bo = 0;
- int cas = 0;
- while (~scanf("%d%*c", &k) && k) {
- if (bo) printf("\n");
- else bo = 1;
- printf("CASE %d\n", ++cas);
- gao.solve();
- }
- return 0;
- }
UVA 10526 - Intellectual Property (后缀数组)的更多相关文章
- UVA 12206 - Stammering Aliens(后缀数组)
UVA 12206 - Stammering Aliens 题目链接 题意:给定一个序列,求出出现次数大于m,长度最长的子串的最大下标 思路:后缀数组.搞出height数组后,利用二分去查找就可以 这 ...
- Uva 12361 File Retrieval 后缀数组+并查集
题意:有F个单词,1 <= F <=60 , 长度<=10^4, 每次可以输入一个字符串,所有包含该字串的单词会形成一个集合. 问最多能形成多少个不同的集合.集合不能为空. 分析:用 ...
- POJ 3294 UVA 11107 Life Forms 后缀数组
相同的题目,输出格式有区别. 给定n个字符串,求最长的子串,使得它同时出现在一半以上的串中. 不熟悉后缀数组的童鞋建议先去看一看如何用后缀数组计算两个字符串的最长公共子串 Ural1517 这道题的思 ...
- UVA 12338 - Anti-Rhyme Pairs(后缀数组+RMQ)
UVA 12338 - Anti-Rhyme Pairs 题目链接 题意:给定一些字符串,每次询问求出两个字符串的最长公共前缀的长度 思路:把字符串排序,就能求出height和rank数组,然后利用R ...
- UVa 10829 L-Gap Substrings (后缀数组+rmq)
题意:给定上一个串,问你多少种UVU这一种形式的串,其中U不为空并且V的长度给定了. 析:枚举 U 的长度L,那么U一定是经过 0 L 2L 3L .... 其中的一个,所以求两个长度反lcp,一个向 ...
- UVA 11475 后缀数组/KMP
题目链接: 题意:给定一个只含字母的字符串,求在字符串末尾添加尽量少的字符使得字符串为回文串. 思路:因为只能从末尾添加字符,所以其实求的是最长的后缀回文串.那么添加的字符为除了这个原串的最长后缀回文 ...
- UVA 11475 Extend to Palindrome(后缀数组+ST表)
[题目链接] http://acm.hust.edu.cn/vjudge/problem/27647 [题目大意] 给出一个字符串,要求在其后面添加最少的字符数,使得其成为一个回文串.并输出这个回文串 ...
- 后缀数组LCP + 二分 - UVa 11107 Life Forms
Life Forms Problem's Link Mean: 给你n个串,让你找出出现次数大于n/2的最长公共子串.如果有多个,按字典序排列输出. analyse: 经典题. 直接二分判断答案. 判 ...
- UVA 12338:Anti-Rhyme Pairs(后缀数组+ST表)
[题目链接] click [题目大意] 给出一些字符串,询问查询任意两个字符串的最长公共前缀 [题解] 将字符串拼接,对拼接的字符串做后缀数组,对于查询的两个字符串, 只要在height数组上查询区间 ...
随机推荐
- iOS学习笔记45-Swift(五)协议
一.Swift协议 协议是为方法.属性等定义一套规范,没有具体的实现,类似于Java中的抽象接口,它只是描述了方法或属性的骨架,而不是实现.方法和属性实现还需要通过定义类,函数和枚举完成. 1. 协议 ...
- python多进程(multiprocessing)
最近有个小课题,需要用到双进程,翻了些资料,还算圆满完成任务.记录一下~ 1.简单地双进程启动 同时的调用print1()和print2()两个打印函数,代码如下: #/usr/bin/python ...
- hdoj--1010<dfs+奇偶剪枝>
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1010 题目描述:在n*m的矩阵中,有一起点和终点,中间有墙,给出起点终点和墙,并给出步数,在该步数情况 ...
- NOIP2017整数 【线段树】
题目 题目背景 在人类智慧的山巅,有着一台字长为10485761048576 位(此数字与解题无关)的超级计算机,著名理论计算机科 学家P博士正用它进行各种研究.不幸的是,这天台风切断了电力系统,超级 ...
- 刷题总结——树有几多愁(51nod1673 虚树+状压dp+贪心)
题目: lyk有一棵树,它想给这棵树重标号. 重标号后,这棵树的所有叶子节点的值为它到根的路径上的编号最小的点的编号. 这棵树的烦恼值为所有叶子节点的值的乘积. lyk想让这棵树的烦恼值最大,你只需输 ...
- Scrapy学习-12-使用DownloaderMiddleware随机修改User-Agent
随机替换请求头中的User-Agent 基于github开源项目,实现User-Agent的动态切换和管理 https://github.com/hellysmile/fake-useragent ...
- php的fastcgi_finish_request()函数
php的fastcgi_finish_request()函数 功能: 此函数冲刷(flush)所有响应的数据给客户端并结束请求. 这使得客户端结束连接后,需要大量时间运行的任务能够继续运行. 返回值: ...
- Oracle For 循环添加数据
自己亲自使用的,绝对OK --添加数据declare i number; --用for实现 begin for i in 0 .. 500 loop insert into cust(custsn,t ...
- Careercup | Chapter 5
5.1 You are given two 32-bit numbers, N andM, and two bit positions, i and j. Write a method to inse ...
- win7快捷键和ubuntu快捷键
http://www.cnblogs.com/xfiver/archive/2010/12/08/1899905.html http://www.pc841.com/article/20121203- ...