bzoj4502 串

标签: 解题报告 NOIP bzoj AC自动机 dp
490人阅读 评论(0) 收藏 举报
分类:

题目背景:

bzoj4502

分析:

20% 解法:

暴力枚举前缀,然后两两枚举形成新串,然后有hash判重(用set的宝宝,爆成了5分·····)

50% 解法:

将集合中的所有的字符串构建成一个AC自动机,然后,注意到每个字符串在AC自动机上的匹配路径应该是唯一的,那么我们可以考虑dpf[i][j][k]表示当前长度为i的字符串,匹配到j状态,第一次的失配的位置在k处,然后直接暴力枚举下一个字符的位置,然后在AC自动机上跑转移就可以了,注意每一次的时的状态的深度一定要大于当前的第一次失配后的匹配长度,否则意味着无法满足题目的信息

100% 解法:

我们可以发现,在上一道题中的在第一次失配前的长度是不需要记录的,那么我们就可以考虑优化状态,f[i][j]表示,当前在第一次失配后的长度,然后当前匹配到的状态,同样注意,每一次失配的状态的深度一定要大于当前的i否则不满足形成前缀。

注意:因为我们一开始就是枚举的在第一次失配后走了多长的长度,但是可能我们可以选择直接在第一次失配后不再往后走,也就是直接将原来的某个字符串的一部分,直接改成一段前缀,想要判断这一个状态是否满足,只需要直接判断当前的fail指针是否为根,如果不是,则就意味着,是可以通过将当前的一段后缀替换为另一段前缀来实现。

Source

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;

const int MAXL = 30 + 5;
const int MAXN = 10000 + 10;

struct node {
	node *next[26], *fail;
	bool exist[26];
	int deep;
	node() {
		memset(next, 0, sizeof(next)), fail = NULL;
		memset(exist, 0, sizeof(exist)), deep = 0;
	}
} trie[MAXL * MAXN], *root, *tot = trie;

long long dp[MAXL][MAXL * MAXN];

inline void insert(char *s) {
	int len = strlen(s);
	node *cur = root;
	for (int i = 0; i < len; ++i) {
		if (!cur->next[s[i] - 'a']) cur->next[s[i] - 'a'] = tot++;
		cur->exist[s[i] - 'a'] = true, cur = cur->next[s[i] - 'a'];
	}
}

inline void build_fail() {
	queue q;
	q.push(root), root->deep = 0;
	while (!q.empty()) {
		node *cur = q.front(); q.pop();
		for (int i = 0; i < 26; ++i) {
			if (cur->next[i]) {
				node *v = cur->fail;
				while (v && !v->next[i]) v = v->fail;
				cur->next[i]->fail = (v ? v->next[i] : root);
				q.push(cur->next[i]), cur->next[i]->deep = cur->deep + 1;
			} else {
				node *v = cur->fail;
				while (v && !v->next[i]) v = v->fail;
				cur->next[i] = (v ? v->next[i] : root);
			}
		}
	}
}

inline void dp_on_AC_automation() {
	long long ans = 0;
	/*判断可以直接通过改变原串的一部分*/ 
	for (node *i = trie; i != tot; ++i) if (i->fail != root) ans++;
	/*计算需要两串进行拼接的部分的开头位置*/ 
	for (node *i = trie; i != tot; ++i)
		for (int j = 0; j < 26; ++j)
			if (!i->exist[j] && i->next[j] != root)
				dp[1][i->next[j] - trie]++;
	/*枚举走到的状态和当前的步数*/ 
	for (int i = 1; i < MAXL; ++i)
		for (node *j = trie; j != tot; ++j) {
			if (dp[i][j - trie]) {
				ans += dp[i][j - trie];
				for (int k = 0; k < 26; ++k)
					if (j->exist[k] || j->next[k]->deep > i)
						dp[i + 1][j->next[k] - trie] += dp[i][j - trie];
			}
		}
	cout << ans;	
}

int n;
char s[MAXL];
int main() {
	root = new node();
	cin >> n;
	for (int i = 1; i <= n; ++i) 
		cin >> s, insert(s);
	build_fail();
	dp_on_AC_automation();
	return 0;
}

 

 

 

查看评论

BZOJ4502: 串

Description 兔子们在玩字符串的游戏。首先,它们拿出了一个字符串集合S,然后它们定义一个字 符串为“好”的,当且仅当它可以被分成非空的两段,其中每一段都是字符串集合S中某个字符串的前...
  • wxh010910
  • wxh010910
  • 2017-04-10 19:29:58
  • 341

BZOJ4574: [Zjoi2016]线段树

Description 小Yuuka遇到了一个题目:有一个序列a_1,a_2,?,a_n,q次操作,每次把一个区间内的数改成区间内的最大值,问 最后每个数是多少。小Yuuka很快地就使用了线段...
  • wxh010910
  • wxh010910
  • 2017-03-26 21:05:32
  • 455

bzoj4503 两个串

两个串 题目背景: bzoj4503 分析: 我相信各路大牛在看到这道题的时候一定会不屑的表示这个不是套路题吗····的确这真心就是一个简单的套路,快速傅立叶变换(FFT),我...
  • scar_lyw
  • scar_lyw
  • 2017-03-06 19:46:21
  • 291

BZOJ4502: 串(字符串,AC自动机)

前言: BZOJ P4502 串 题面: 输入格式: 输出格式: 样例输入: 样例输出: 数据范围: 分析: 然后开始码代码: 全代码: 前言: 完全不会AC自动机...
  • qq_39596588
  • qq_39596588
  • 2018-03-15 19:57:51
  • 32

识别它们为字符串

什么是字符串? 第一个C++你写的程序,可能看起来像这样: #include int main() { std::cout ...
  • shazhugw
  • shazhugw
  • 2017-12-11 16:04:09
  • 23

字符串游戏

题目大意题解瞎猜想和画图得到一个不好说的结论。 用诡异的单调栈做。#include #include #define fo(i,a,b) for(i=a;i=b;i--) using namespa...
  • WerKeyTom_FTD
  • WerKeyTom_FTD
  • 2017-06-22 20:16:12
  • 172

BZOJ4502 串

Description兔子们在玩字符串的游戏。首先,它们拿出了一个字符串集合S,然后它们定义一个字 符串为“好”的,当且仅当它可以被分成非空的两段,其中每一段都是字符串集合S中某个字符串的前缀。 ...
  • yzyyylx
  • yzyyylx
  • 2018-03-15 18:43:23
  • 42

数据结构 串的操作

  • 2011年09月28日 22:56
  • 1.94MB
  • 下载

bzoj4504: K个串【主席树区间操作+优先队列】

Description 兔子们在玩k个串的游戏。首先,它们拿出了一个长度为n的数字序列,选出其中的一 个连续子串,然后统计其子串中所有数字之和(注意这里重复出现的数字只被统计一次)。 兔子们想知...
  • cdsszjj
  • cdsszjj
  • 2018-02-28 16:19:22
  • 35

小心放开地玩字符串。。。。

01./* 02.* 程序的版权和版本声明部分 03.* Copyright (c)2012, 烟台大学计算机学院学生 04.* All rightsreserved. 05.* 文件...
  • dongwanpeng00
  • dongwanpeng00
  • 2012-12-11 18:53:48
  • 365
    个人资料
    专栏达人 持之以恒
    等级:
    访问量: 2万+
    积分: 2169
    排名: 2万+
    博客专栏
    最新评论