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. BZOJ1636&&1699:[USACO2007JAN]Balanced Lineup

    浅谈\(RMQ\):https://www.cnblogs.com/AKMer/p/10128219.html 题目传送门:https://lydsy.com/JudgeOnline/problem. ...

  2. 深入理解javascript中的立即执行函数

    这篇文章主要介绍了深入理解javascript中的立即执行函数,立即执行函数也叫立即调用函数,通常它的写法是用(function(){…})()包住业务代码,使用jquery时比较常见,需要的朋友可以 ...

  3. 串口编程3:使用串口读取GPS信息

    关于GPS的使用,参考. 本文主要参考的博客,在此表示感谢!!! 主函数 主函数gps_main.c,这里便涉及到了串口的打开,读操作,以及调用了串口设置函数: #include <stdio. ...

  4. MongoDB分析工具之二:MongoDB分析器Profile

    MongoDB优化器profile 在MySQL 中,慢查询日志是经常作为我们优化数据库的依据,那在MongoDB 中是否有类似的功能呢?答案是肯定的,那就是MongoDB Database Prof ...

  5. jquery easyui 推荐博客 (MVC+EF+EasyUI+Bootstrap)

    构建ASP.NET MVC5+EF6+EasyUI 1.4.3+Unity4.x注入的后台管理系统(52)-美化EasyUI皮肤和图标   系列目录 我很久以前就想更新系统的皮肤功能,Easyui 自 ...

  6. File 类 操作实例

    File 操作 <介绍> 尽管java.io定义的大多数类是实行流式操作的,File类不是.它直接处理文件和文件系统.也就是说,File类没有指定信息怎样从文件读取或向文件存储:它描述了文 ...

  7. 把Nutch爬虫部署到Hadoop集群上

    原文地址:http://cn.soulmachine.me/blog/20140204/ 把Nutch爬虫部署到Hadoop集群上 Feb 4th, 2014 | Comments 软件版本:Nutc ...

  8. CodeForces 489D Unbearable Controversy of Being (不知咋分类 思维题吧)

    D. Unbearable Controversy of Being time limit per test 1 second memory limit per test 256 megabytes ...

  9. 8、泛型程序设计与c++标准模板库1、泛型程序设计的概念和术语

    有效地利用已有的成果,将经典的.优秀的算法标准化.模块化,从而提高软件的生产率,是软件产业化的需求,为了实现这一需求,不仅需要面向对象设计思想,而且需要泛型程序设计思想. c++语言提供的标准模板库( ...

  10. HDU 5974 A Simple Math Problem (解方程)

    题意:给定a和b,求一组满足x+y=a && lcm(x, y)=b. 析:x+y = a, lcm(x, y) = b,=>x + y = a, x * y = b * k,其 ...