Bazinga HDU - 5510 不可做的暴力
http://acm.hdu.edu.cn/showproblem.php?pid=5510
想了很久队友叫我用ufs + kmp暴力过去了。
fa[x] = y表示x是y的子串,所以只有fa[x] == x才需要kmp一次。
那么这样的话,如果全部都不互为子串的话,复杂度还是爆咋的。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <string>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <cstdlib>
#include <ctime>
#define X first
#define Y second
#define clr(u,v); memset(u,v,sizeof(u));
#define in() freopen("data.txt","r",stdin);
#define out() freopen("ans","w",stdout);
#define Clear(Q); while (!Q.empty()) Q.pop();
#define pb push_back
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const ll INF = 1e17;
const int inf = 0x3f3f3f3f;
const int maxn = + ;
int tonext[][maxn];
void get_next(char sub[], int tonext[], int lensub) {
int i = , j = ;
tonext[] = ;
while (i <= lensub) {
if (j == || sub[i] == sub[j]) {
tonext[++i] = ++j;
} else j = tonext[j];
}
}
int kmp(char str[], char sub[], int lenstr, int lensub, int tonext[]) {
int i = , j = ;
while (i <= lenstr) {
if (j == || str[i] == sub[j]) {
++i, ++j;
} else j = tonext[j];
if (j == lensub + ) return true;
}
return false;
}
char str[][maxn];
int len[];
int f;
int fa[maxn];
int tofind(int u) {
if (fa[u] == u) return u;
else return fa[u] = tofind(fa[u]);
}
void tomerge(int x, int y) {
x = tofind(x), y = tofind(y);
fa[y] = x;
}
void work() {
int n;
scanf("%d", &n);
for (int i = ; i <= n; ++i) {
scanf("%s", str[i] + );
len[i] = strlen(str[i] + );
get_next(str[i], tonext[i], len[i]);
fa[i] = i;
}
printf("Case #%d: ", ++f);
int ans = -;
for (int i = ; i <= n; ++i) {
for (int j = i - ; j >= ; --j) {
if (tofind(j) != j) continue;
if (kmp(str[i], str[j], len[i], len[j], tonext[j])) {
tomerge(i, j); //合并的方向,小的合并去大的
} else {
ans = i;
}
// if (kmp(str[j], str[i], len[j], len[i], tonext[i])) {
// tomerge(j, i);
// }
}
}
printf("%d\n", ans);
return;
} int main() {
#ifdef local
in();
#else
#endif
int t;
scanf("%d", &t);
while (t--) work();
return ;
}
有一个超时的AC自动机算法。复杂度O(T * n * lenstr * lenstr)
首先所有串buildFail
然后对于每一个串,爬Fail树。从后往前枚举
那么每个串跑一次Fail树的时候就能知道有多少个子串。成立的条件是子串个数 < i,则i位置成立。
如果后面的串使得匹配子串个数变大的话,那么是不影响的,说明在后面枚举的时候那个位置就应该是已经成立的了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <string>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <cstdlib>
#include <ctime>
#define X first
#define Y second
#define clr(u,v); memset(u,v,sizeof(u));
#define in() freopen("2.h","r",stdin);
#define out() freopen("ans","w",stdout);
#define Clear(Q); while (!Q.empty()) Q.pop();
#define pb push_back
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const ll INF = 1e17;
const int inf = 0x3f3f3f3f;
char str[][ + ];
struct Node {
int flag, id;
struct Node *Fail;
struct Node *pNext[];
} tree[ + ];
int t;
struct Node * create() {
struct Node * p = &tree[t++];
p->flag = ;
p->Fail = NULL;
p->id = t - ;
for (int i = ; i < ; ++i) p->pNext[i] = NULL;
return p;
}
void toinsert(struct Node **T, char str[]) {
struct Node *p = *T;
if (p == NULL) p = *T = create();
for (int i = ; str[i]; ++i) {
int id = str[i] - 'a';
if (p->pNext[id] == NULL) {
p->pNext[id] = create();
}
p = p->pNext[id];
}
p->flag++;
}
struct Node * que[ + ];
void BuildFlag(struct Node **T) {
struct Node *p = *T;
struct Node *root = *T;
if (p == NULL) return ;
int head = , tail = ;
que[tail++] = root;
while (head < tail) {
p = que[head];
for (int i = ; i < ; ++i) {
if (p->pNext[i] != NULL) {
if (p == root) {
p->pNext[i]->Fail = root;
} else {
struct Node * FailNode = p->Fail;
while (FailNode != NULL) {
if (FailNode->pNext[i] != NULL) {
p->pNext[i]->Fail = FailNode->pNext[i];
break;
}
FailNode = FailNode->Fail;
}
}
que[tail++] = p->pNext[i];
} else if (p == root) {
p->pNext[i] = root;
} else {
p->pNext[i] = p->Fail->pNext[i];
}
}
head++;
}
}
int vis[ + ], DFN;
int searchAC(struct Node *T, char str[], int val) {
DFN++;
int ans = ;
struct Node * p = T;
struct Node * root = T;
if (p == NULL) return ;
for (int i = ; str[i]; ++i) {
int id = str[i] - 'a';
p = p->pNext[id];
struct Node * temp = p;
while (temp != root && vis[temp->id] != DFN) {
vis[temp->id] = DFN;
ans += temp->flag;
temp = temp->Fail;
if (ans >= val) return false;
}
}
return true;
}
int f;
void work() {
t = ;
printf("Case #%d: ", ++f);
int n;
scanf("%d", &n);
struct Node * T = NULL;
for (int i = ; i <= n; ++i) {
scanf("%s", str[i] + );
toinsert(&T, str[i]);
}
BuildFlag(&T);
for (int i = n; i ; --i) {
if(searchAC(T, str[i], i)) {
printf("%d\n", i);
return;
}
}
printf("-1\n");
return;
} int main() {
#ifdef LOCAL
in();
#else
#endif
int t;
scanf("%d", &t);
while (t--) work();
return ;
}
Bazinga HDU - 5510 不可做的暴力的更多相关文章
- Bazinga HDU 5510 Bazinga(双指针)
Bazinga HDU 5510 Bazinga(双指针) 题链 解法:对于串i来说,如果串i是不符合的,那么代表串i之前的字符串都是i的子串,那么我们求一个新的i(定义为ti),如果i是ti 的子串 ...
- Bazinga HDU - 5510【技巧暴力+字符串】
题目:https://vjudge.net/problem/HDU-5510 $2015ACM/ICPC$ 亚洲区沈阳站 题目大意: 输入$t$(表示样例个数) 如何每个样例一个 $n$,表示字符串的 ...
- 【Bazinga HDU - 5510 】【考察strstr()的使用】【贪心】
题意分析 1.题目大致说的是让你输出符合这种条件(在所给的字符串中至少有一个不是它的子串)的字符串对应的label,若没有输出-1: 2.判断子串可以用string.h下的strstr(s1, s2) ...
- hdu 5510 Bazinga(字符串kmp)
Bazinga Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Sub ...
- HDU 2920 分块底数优化 暴力
其实和昨天写的那道水题是一样的,注意爆LL $1<=n,k<=1e9$,$\sum\limits_{i=1}^{n}(k \mod i) = nk - \sum\limits_{i=1}^ ...
- HDU 5510 Bazinga 暴力匹配加剪枝
Bazinga Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5510 ...
- HDU 5510:Bazinga(暴力KMP)
http://acm.hdu.edu.cn/showproblem.php?pid=5510 Bazinga Problem Description Ladies and gentlemen, p ...
- hdu 5510 Bazinga (KMP+暴力标记)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5510 思路: 一开始直接用KMP莽了发,超时了,后面发现如果前面的字符串被后面的字符串包含,那么我们就 ...
- hdu 5510 Bazinga(暴力)
Problem Description Ladies and gentlemen, please sit up straight. Don't tilt your head. I'm serious. ...
随机推荐
- cs2008中头文件交叉编译的问题
使用全局变量 使用基类指针定义在头文件中,在实际使用中强制转型为需要的指针,当然应该也可以存为空指针.
- MySQL复制--最快的从库搭建方法(tar包) -转
最快的从库搭建方法0,准备从库第一次数据备份,临时锁所有表开启窗口1 mysql> flush tables with read lock; Query OK, 0 rows affected ...
- Poj 2328 Guessing Game(猜数字游戏)
一.题目大意 两个小盆友玩猜数字游戏,一个小盆友心里想着1~10中的一个数字,另一个小盆友猜.如果猜的数字比实际的大,则告诉他"too high",小则"too low& ...
- MySQL Sending data导致查询很慢的问题详细分析
这两天帮忙定位一个MySQL查询很慢的问题,定位过程综合各种方法.理论.工具,很有代表性,分享给大家作为新年礼物:) [问题现象] 使用sphinx支持倒排索引,但sphinx从mysql查询源数据的 ...
- Java中“分号”引起的陷阱
对于这类问题而言,难度不大,多半是由于我们有误操作引起的.但在查找问题所在的时候我们有可能需要花费一番功夫了. 实例一: package com.yonyou.test; /** * 测试类 * @a ...
- 关于cin
今天同学调试一个简单的程序的时候发现了问题,我们两个讨论的时候弄出了好多乐子 #include <iostream> using namespace std; int main() { ; ...
- Java探索之旅(1)——概述与控制台输入
使用的课本: Java语言程序设计(基础篇)----西电 李娜(译) 原著: Introduction to Java Progrmming(Eighth Edition) -----Y.Daniel ...
- JavaScript正则表达式应用---replace()
replace()方法使用一个替换值(replacement)替换掉一个匹配模式(pattern)在原字符串中某些或所有的匹配项,并返回替换后的字符串.这个替换模式可以是字符串或者RegExp(正则表 ...
- Linux 静态库(.a)转换为动态库(.so)
Linux 静态库转换为动态库 参考 http://blog.csdn.net/moxuansheng/article/details/5812410 首先将.a文件转为.so文件是可以实现的 原因是 ...
- 2. DVWA亲测命令执行漏洞
先看low级: 提示让我们输入一个IP地址来实现ping,猜测会是在系统终端中实现的, 我们正常输入127.0.0.1: 那我们就可以利用这个使用其他CMD命令 我们输入127.0.0.1& ...