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 不可做的暴力的更多相关文章

  1. Bazinga HDU 5510 Bazinga(双指针)

    Bazinga HDU 5510 Bazinga(双指针) 题链 解法:对于串i来说,如果串i是不符合的,那么代表串i之前的字符串都是i的子串,那么我们求一个新的i(定义为ti),如果i是ti 的子串 ...

  2. Bazinga HDU - 5510【技巧暴力+字符串】

    题目:https://vjudge.net/problem/HDU-5510 $2015ACM/ICPC$ 亚洲区沈阳站 题目大意: 输入$t$(表示样例个数) 如何每个样例一个 $n$,表示字符串的 ...

  3. 【Bazinga HDU - 5510 】【考察strstr()的使用】【贪心】

    题意分析 1.题目大致说的是让你输出符合这种条件(在所给的字符串中至少有一个不是它的子串)的字符串对应的label,若没有输出-1: 2.判断子串可以用string.h下的strstr(s1, s2) ...

  4. hdu 5510 Bazinga(字符串kmp)

    Bazinga Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Sub ...

  5. HDU 2920 分块底数优化 暴力

    其实和昨天写的那道水题是一样的,注意爆LL $1<=n,k<=1e9$,$\sum\limits_{i=1}^{n}(k \mod i) = nk - \sum\limits_{i=1}^ ...

  6. HDU 5510 Bazinga 暴力匹配加剪枝

    Bazinga Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5510 ...

  7. HDU 5510:Bazinga(暴力KMP)

    http://acm.hdu.edu.cn/showproblem.php?pid=5510 Bazinga Problem Description   Ladies and gentlemen, p ...

  8. hdu 5510 Bazinga (KMP+暴力标记)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5510 思路: 一开始直接用KMP莽了发,超时了,后面发现如果前面的字符串被后面的字符串包含,那么我们就 ...

  9. hdu 5510 Bazinga(暴力)

    Problem Description Ladies and gentlemen, please sit up straight. Don't tilt your head. I'm serious. ...

随机推荐

  1. 用Fiddler2来监听HTTP(记:用skydrive sdk访问时,出错后用Fidder抓包分析)

    最近在写一个关于如何上传文件到skydrive的demo, 用REST上传失败. 安装Telerik的Fiddler后, 可以监听http或者https通信, 然后可以在软件中看到返回的json数据或 ...

  2. Project Server调用PSI关闭任务以进行更新锁定任务

    /// <summary> /// 锁定和解锁项目任务 /// </summary> /// <param name="projectuid"> ...

  3. 问题:部署到iis上后Chart图片不显示;结果:使用webchart过程中遇到的一些问题

    使用webchart过程中遇到的一些问题 2013年04月30日 ⁄ 综合 ⁄ 共 4874字 ⁄ 字号 小 中 大 ⁄ 评论关闭   安装条件:1.操作系统如果是2003的,那么需要到sp2补丁2. ...

  4. Java学习路线-知乎

    鼬自来晓 378 人赞同 可以从几方面来看Java:JVM Java JVM:内存结构和相关参数含义 · Issue #24 · pzxwhc/MineKnowContainer · GitHub J ...

  5. maven spring3.2.5

    出现的情形: 开发环境: spring3.2.5 + springmvc +spirngDATA +maven 一. 偶然的spring Junit4测试 加载applicationContext.x ...

  6. service的生命周期以及两种service的差异

    可以看到,两种service的生命周期都相对简单,有一点不同的是,Intentservice每次调用的时候都执行onstartcommand,而boundservice一旦启动了之后,就不会每次执行o ...

  7. SM4算法的c++实现

    百度到的论文已给出算法. flag为1为解密,flag为0是加密. #include<bits/stdc++.h> using namespace std; typedef long lo ...

  8. [#413c] Fountains

    http://codeforces.com/contest/799/problem/C 解题关键:树状数组取最大值,注意先搜索,后加入,此种情况可以取出最大值. 为什么可以取到最大值? 1.当分别用两 ...

  9. C++中的构造函数小结

    对象的初始化 对象时类的实例,类是不占用空间的,对象是占用空间的. 因为类是抽象的,不占用空间的,所以我们不能再定义类的时候对对象进行初始化操作的. 但是,我们可以定义一个函数,在类实例化一个对象的时 ...

  10. SQL笔记:基础篇

    1.BETWEEN AND (查询某个区间的数据) 例如:查询user表中年龄在15-30岁的人 SELECT * FROM user WHERE age between 15 and 30 2.IN ...