UVA 11557 - Code Theft (KMP + HASH)

UVA 11557 - Code Theft

题目链接

题意:给定一些代码文本,然后在给定一个现有文本,找出这个现有文本和前面代码文本,重复连续行最多的这些文本

思路:把每一行hash成一个值,然后对于每一个文本计算最大匹配值,枚举后缀,然后利用KMP去找即可

代码:

#include <cstdio>
#include <cstring>
#include <vector>
#include <string>
#include <iostream>
#include <vector>
using namespace std;

typedef unsigned long long ull;

const ull X = 123;
const int N = 105;

int n, next[1000005];
string name[N];
string s;
vector<int> ans;
vector<ull> code[N];

void hash(string s, int u) {
    string ss = "";
    int l = 0, r = s.length() - 1, len = s.length();;
    while (s[l] == ' ' && l < len) l++;
    while (s[r] == ' ' && r >= 0) r--;
    for (int i = l; i <= r; i++) {
	ss += s[i];
	while (s[i] == ' ' && s[i + 1] == ' ' && i < r) i++;
    }
    if (ss == "") return;
    ull ans = 0;
    for (int i = ss.length() - 1; i >= 0; i--)
	ans = ans * X + ss[i];
    code[u].push_back(ans);
}

void build(int i) {
    code[i].clear();
    while (getline(cin, s) && s != "***END***") {
	hash(s, i);
    }
}

vector<ull> T;

void getnext() {
    int N = T.size();
    next[0] = next[1] = 0;
    int j = 0;
    for (int i = 2 ; i <= N; i++) {
	while (j && T[i - 1] != T[j]) j = next[j];
	if (T[i - 1] == T[j]) j++;
	next[i] = j;
    }
}

int find() {
    int ans = 0;
    int N = code[n].size(), m = T.size(), j = 0;
    for (int i = 0; i < N; i++) {
	while (j && code[n][i] != T[j]) j = next[j];
	if (code[n][i] == T[j]) j++;
	ans = max(ans, j);
	if (j == m)
	    return m;
    }
    return ans;
}

int cal(int u) {
    int ans = 0;
    int sz1 = code[u].size();
    for (int i = 0; i < sz1; i++) {
	T.clear();
	for (int j = i; j < sz1; j++)
	    T.push_back(code[u][j]);
	getnext();
	ans = max(ans, find());
    }
    return ans;
}

void solve() {
    int Max = 0;
    ans.clear();
    for (int i = 0; i < n; i++) {
	int tmp = cal(i);
	if (tmp > Max) {
	    Max = tmp;
	    ans.clear();
	    ans.push_back(i);
	}
	else if (tmp == Max) ans.push_back(i);
    }
    cout << Max;
    if (Max) {
	for (int i = 0; i < ans.size(); i++)
	    cout << " " << name[ans[i]];
    }
    cout << endl;
}

int main() {
    while (cin >> n) {
	getchar();
	for (int i = 0; i < n; i++) {
	    getline(cin, name[i]);
	    build(i);
	}
	build(n);
	solve();
    }
    return 0;
}
时间: 2024-08-25 08:04:03

UVA 11557 - Code Theft (KMP + HASH)的相关文章

uva 11557 - Code Theft(KMP)

题目链接:uva 11557 - Code Theft 题目大意:给定n个文本,每个文本有一个文本名,现在给出一个文本,求给定文本和n个文本中连续相同行数最大值,并且输出文本名,注意为0时不用输出其它的文本名. 解题思路:将每个字符串用映射成一个hash值,然后对匹配文本枚举后缀,建立失配数组进行KMP匹配,记录下每个文本的匹配最大值. #include <cstdio> #include <cstring> #include <map> #include <st

UVA 11754 - Code Feat(数论)

UVA 11754 - Code Feat 题目链接 题意:给定一个c个x, y1,y2,y3..yk形式,前s小的答案满足s % x在集合y1, y2, y3 ... yk中 思路:LRJ大白例题,分两种情况讨论 1.所有x之积较小时候,暴力枚举每个集合选哪个y,然后中国剩余定理求解 2.所有x之积较大时候,选定一个k/x尽可能小的序列,枚举x * t + y (t = 1, 2, 3...)去暴力求解. 代码: #include <stdio.h> #include <string.

UVA - 10298 Power Strings (KMP求字符串循环节)

Description Problem D: Power Strings Given two strings a and b we define a*b to be their concatenation. For example, if a = "abc" and b = "def" then a*b = "abcdef". If we think of concatenation as multiplication, exponentiati

UVA 475 - Wild Thing(KMP)

UVA 475 - Wild Thing 题目链接 题意:给定一个带通配符的文件名作为格式,后面跟一个文件名,要求输出符合格式的文件名 思路:先把带通配符的文件名根据星号位置进行分解,然后对于每个文件名去判断,判断的方法用KMP,如果格式的每段都能在文件名中不断往后一一匹配上,那么就是可以的,注意考虑开头和结尾没有星号的情况,还有这题就是如果找不到一个合适的,就什么都不输出,包括换行 代码: #include <cstdio> #include <cstring> #include

UVA 10298 - Power Strings(KMP)

UVA 10298 - Power Strings 题目链接 题意:本意其实就是,给定一个字符串,求出最小循环节需要几次循环出原字符串 思路:利用KMP中next数组的性质,n - next[n]就是最小循环节,然后n / 循环节就是答案 代码: #include <cstdio> #include <cstring> const int N = 1000005; char str[N]; int next[N]; void getnext() { int n = strlen(s

uva 11754 - Code Feat(中国剩余定理+暴力)

题目链接:uva 11754 - Code Feat 题目大意:求一个数N,给出C和S,表示有C个条件,每个条件有X 和 k,然后是该个条件的k个yi,即NmodX=yj,输出满足的最小的S个N,要求正整数. 解题思路:total为所有的k的乘积,也就是可以作为一组完整限定条件的可能数,当个确定条件可以用中国剩余定理处理.但是如果total太大的话,处理的情况比较多.不过total数大的时候,可以通过枚举N来判断,找到一组k/x最小的最为枚举基准,然后判断即可. #include <cstdio

Codeforces 526D Om Nom and Necklace kmp+hash

题目链接:点击打开链接 题意: 给出长度为n的字符串,常数k 下面一个长度为n的字符串. 问: for(int i = 1; i <= n; i++){ 字符串的前i个字符 能否构成 形如A+B+A+B+A+B+A的形式,其中A有k+1个,B有k个 A和B是2个任意的字符串(也可以为空串) 若可以构成则输出1,否则输出0 } 思路: POJ1961 先用kmp求一个前缀循环节,. 我们观察 ABABABA => AB, AB, AB, A 所以前缀循环节有K个,而后面的A是尽可能地和AB长度接

UVa 11996 Jewel Magic (splay + Hash + 二分)

题意:给定一个长度为n的01串,你的任务是依次执行如表所示的m条指令: 1 p c 在第p个字符后插入字符,p = 0表示在整个字符串之前插入2 p 删除第p个字符,后面的字符往前移3 p1 p2反转第p1到第p2个字符4 p1 p2输出从p1开始和p2开始的两个后缀的LCP. 析:对于前三个操作,splay 很容易就可以解决,但是对于最后一个操作,却不是那么容易,因为这是动态的,所以我们也要维护一个可以动态的,这就可以用Hash来解决,由于要翻转,所以要维护两个,一个正向的,一个反向的.在操作

【POJ2185】【KMP + HASH】Milking Grid

Description Every morning when they are milked, the Farmer John's cows form a rectangular grid that is R (1 <= R <= 10,000) rows by C (1 <= C <= 75) columns. As we all know, Farmer John is quite the expert on cow behavior, and is currently wri