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. bzoj 3924 幻想乡战略游戏 —— 动态点分治

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3924 参考了博客:https://blog.csdn.net/qq_34564984/art ...

  2. category extension

    1 category 分类,只能添加方法,添加的方法成为原来类的一部分,达到扩展类的目的,可以被子类继承 主要给没有源代码的类 添加方法,团队合作项目互不影响,不该动原有类的基础上添加方法 self ...

  3. java代码简单练习

    总结: package com.ds; import java.awt.Color; import java.awt.FlowLayout; import javax.swing.JFrame; im ...

  4. 十二:JAVA I/O

     输入模式                                                          输出模式 ⑴字节输入流:InputStream ⑵字节输出流:Output ...

  5. sql 查看表结构

    sqlserver 查看表结构 exec sp_help @TableName --得到表信息.字段,索引.constraint. exec sp_pkeys @TableName --得到主键. e ...

  6. linux命令-任务计划-cron

    任务计划,有时间规律的执行某些事情. 查看任务计划:crontab -l 指定用户:crontab -l  -u 用户名 该用户没有任务计划. 自定义任务计划 进入一个操作和vim类似的界面 用空格分 ...

  7. 关于UI性能优化

    1.使用已经有的VIEW,而不是每次都去新生成一个 2.创建自定义类来进行组件和数据的缓存,在下一次调用的时候直接从FLAG中取出 3.分页,预加载 使用VIEWSTUB进行调用时加载 VIEWSTU ...

  8. Unusual Sequences

    题意: 求解合为 y 的总体 gcd 为 x 的正整数非空序列个数. 解法: 特判一下后,原问题等价于合为 s = y/x 的整体gcd为1的正整数序列个数. 1.$ans = \sum_{\sum{ ...

  9. Ubuntu 安装Logstash

    Logstash 包是从同一存储库中可用,如 Elasticsearch,和我们已经安装了该公钥,因此,让我们共创 Logstash 源列表︰ echo 'deb http://packages.el ...

  10. 【mysql格式化日期】

    date_format(now(),'%Y-%c-%d'): 1. DATE_FORMAT() 函数用于以不同的格式显示日期/时间数据. DATE_FORMAT(date,format) format ...