【bzoj2553】【beijing2008】【禁忌】【AC自动机+矩阵乘法】

2024-02-20 15:08

本文主要是介绍【bzoj2553】【beijing2008】【禁忌】【AC自动机+矩阵乘法】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Description

       Magic Land上的人们总是提起那个传说:他们的祖先John在那个东方岛屿帮助Koishi与其姐姐Satori最终战平。而后,Koishi恢复了读心的能力……

      

如今,在John已经成为传说的时代,再次造访那座岛屿的人们却发现Koishi遇到了新麻烦。

       这次她遇到了Flandre Scarlet——她拥有可以使用禁忌魔法而不会受到伤害的能力。

       为了说明什么是禁忌魔法及其伤害,引入以下概念:

1.字母集A上的每个非空字符串对应了一个魔法。

其中A是包含了前alphabet个小写字母的集合。

2.有一个集合T,包含了N个字母集A上的字符串

T中的每一串称为一个禁忌串(Taboo string

3.一个魔法,或等价地,其对应的串s因为包含禁忌而对使用者造成的伤害按以下方式确定:

           把s分割成若干段,考虑其中是禁忌串的段的数目,不同的分割可能会有不同的数目,其最大值就是这个伤害。

      

由于拥有了读心的能力,Koishi总是随机地使用Flandre Scarlet的魔法,可以确定的是,她的魔法正好对应字母集A上所有长度为len的串

但是,Flandre Scarlet所使用的一些魔法是带有禁忌的,由于其自身特性,她可以使用禁忌魔法而不受到伤害,而Koishi就不同了。可怜的Koishi每一次使用对方的魔法都面临着受到禁忌伤害的威胁。

 

       你现在需要计算的是如果Koishi使用对方的每一个魔法的概率是均等的,那么每一次随机使用魔法所受到的禁忌伤害的期望值是多少。

 

Input

第一行包含三个正整数N、len、alphabet

接下来N行,每行包含一个串Ti,表示禁忌串。

Output

一个非负实数,表示所受到禁忌伤害的期望值。

 

Sample Input

2 4 2

aa

abb

Sample Output

0.75

【样例1解释】
一共有2^4 = 16种不同的魔法。

需要注意的是“aabb”的禁忌伤害是1而不是2。

HINT

100%的数据中N ≤ 5,len ≤109,1 ≤ alphabet ≤ 26


在所有数据中,有不少于40%的数据中:N = 1


数据保证每个串Ti的长度不超过15,并且不是空串。


数据保证每个Ti均仅含有前alphabet个小写字母。


数据保证集合T中没有相同的元素,即对任意不同的ij,有TiTj


【评分方法】


对于每一组数据,如果没有得到正确的输出(TLE、MLE、RTE、输出格式错误等)得0分。


否则:设你的输出是YourAns,标准输出是StdAns


MaxEPS = max(1.0 , StdAns)×10-6


如果|YourAns – StdAns| ≤ MaxEPS则得10分,否则得0分。


即:你的答案需要保证相对误差或绝对误差不超过10-6。‘

题解:

           考虑如何划分才能得到最多的禁忌串. 显然是贪心的划分,从头开始碰到一个禁忌串就结束重新匹配.

           我们对所有禁忌串建AC自动机.

           对于非单词节点按概率向其他点转移.

           对于单词节点我们连向起始节点,代表匹配到这个点就重新开始匹配.

           但这样我们没法统计答案.

           所以新建一个点,单词节点也向这个点连边,这个点向自身连概率为1的边.

           这样我们求出转移矩阵a.将这个矩阵乘上len遍即可.

           最后答案就是a[1][新节点]的值.

 代码:

           

#include<iostream>
#include<cstdio>
#include<cstring>
#define N 100
using namespace std;
int a[N][30],pos[N],cnt=1,n,m,l,fail[N],q[N];
char ch[N];
struct use{long double a[N][N];use(){memset(a,0,sizeof(a));}friend use operator*(use a,use b){use ans;for (int i=0;i<=cnt;i++)for (int j=0;j<=cnt;j++)for (int k=0;k<=cnt;k++)ans.a[i][j]+=a.a[i][k]*b.a[k][j];return ans;}friend use operator^(use a,int b){use ans;for (int i=0;i<=cnt;i++) ans.a[i][i]=1;for (int i=b;i;i>>=1,a=a*a) if (i&1) ans=ans*a;return ans;}
}c; 
void insert(){int len=strlen(ch),now=1;for (int i=0;i<len;i++){int u=ch[i]-'a'+1;if (a[now][u]) now=a[now][u];else a[now][u]=++cnt,now=a[now][u];}pos[now]=1;
}
void getfail(){int h(0),t(1);q[0]=1;fail[1]=0;while (h<t){int u=q[h++];for (int i=1;i<=m;i++){int k=fail[u];while (!a[k][i]) k=fail[k];if (a[u][i]){fail[a[u][i]]=a[k][i];if (pos[a[k][i]]) pos[a[u][i]]=1;q[t++]=a[u][i];} else a[u][i]=a[k][i];}}
}
void getmatrix(){long double temp=1.0/(long double)m;for (int i=1;i<=cnt;i++)for (int j=1;j<=m;j++)if (pos[a[i][j]]){c.a[i-1][0]+=temp;c.a[i-1][cnt]+=temp;}else c.a[i-1][a[i][j]-1]+=temp;c.a[cnt][cnt]=1.0;
}
int main(){scanf("%d%d%d",&n,&l,&m);for (int i=1;i<=n;i++){scanf("%s",&ch);insert();}for (int i=1;i<=m;i++) a[0][i]=1; getfail();getmatrix();/*for (int i=0;i<=cnt;i++){for (int j=0;j<=cnt;j++)cout<<c.a[i][j]<<' ';cout<<endl;}*/c=c^l;printf("%.8lf\n",(double)c.a[0][cnt]);    
} 

这篇关于【bzoj2553】【beijing2008】【禁忌】【AC自动机+矩阵乘法】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/728614

相关文章

hdu 4565 推倒公式+矩阵快速幂

题意 求下式的值: Sn=⌈ (a+b√)n⌉%m S_n = \lceil\ (a + \sqrt{b}) ^ n \rceil\% m 其中: 0<a,m<215 0< a, m < 2^{15} 0<b,n<231 0 < b, n < 2^{31} (a−1)2<b<a2 (a-1)^2< b < a^2 解析 令: An=(a+b√)n A_n = (a +

hdu 3065 AC自动机 匹配串编号以及出现次数

题意: 仍旧是天朝语题。 Input 第一行,一个整数N(1<=N<=1000),表示病毒特征码的个数。 接下来N行,每行表示一个病毒特征码,特征码字符串长度在1—50之间,并且只包含“英文大写字符”。任意两个病毒特征码,不会完全相同。 在这之后一行,表示“万恶之源”网站源码,源码字符串长度在2000000之内。字符串中字符都是ASCII码可见字符(不包括回车)。

POJ 1625 自动机

给出包含n个可见字符的字符集,以下所提字符串均由该字符集中的字符构成。给出p个长度不超过10的字符串,求长为m且不包含上述p个字符串的字符串有多少个。 g++提交 int mat[108][108] ;int matn ;int N ;map<char ,int> to ;//ACconst int maxm = 108 ;const int kin

zoj 3228 ac自动机

给出一个字符串和若干个单词,问这些单词在字符串里面出现了多少次。单词前面为0表示这个单词可重叠出现,1为不可重叠出现。 Sample Input ab 2 0 ab 1 ab abababac 2 0 aba 1 aba abcdefghijklmnopqrstuvwxyz 3 0 abc 1 def 1 jmn Sample Output Case 1 1 1 Case 2

D4代码AC集

贪心问题解决的步骤: (局部贪心能导致全局贪心)    1.确定贪心策略    2.验证贪心策略是否正确 排队接水 #include<bits/stdc++.h>using namespace std;int main(){int w,n,a[32000];cin>>w>>n;for(int i=1;i<=n;i++){cin>>a[i];}sort(a+1,a+n+1);int i=1

hdu 6198 dfs枚举找规律+矩阵乘法

number number number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Problem Description We define a sequence  F : ⋅   F0=0,F1=1 ; ⋅   Fn=Fn

线性代数|机器学习-P35距离矩阵和普鲁克问题

文章目录 1. 距离矩阵2. 正交普鲁克问题3. 实例说明 1. 距离矩阵 假设有三个点 x 1 , x 2 , x 3 x_1,x_2,x_3 x1​,x2​,x3​,三个点距离如下: ∣ ∣ x 1 − x 2 ∣ ∣ 2 = 1 , ∣ ∣ x 2 − x 3 ∣ ∣ 2 = 1 , ∣ ∣ x 1 − x 3 ∣ ∣ 2 = 6 \begin{equation} ||x

【线性代数】正定矩阵,二次型函数

本文主要介绍正定矩阵,二次型函数,及其相关的解析证明过程和各个过程的可视化几何解释(深蓝色字体)。 非常喜欢清华大学张颢老师说过的一段话:如果你不能用可视化的方式看到事情的结果,那么你就很难对这个事情有认知,认知就是直觉,解析的东西可以让你理解,但未必能让你形成直觉,因为他太反直觉了。 正定矩阵 定义 给定一个大小为 n×n 的实对称矩阵 A ,若对于任意长度为 n 的非零向量 ,有 恒成

python科学计算:NumPy 线性代数与矩阵操作

1 NumPy 中的矩阵与数组 在 NumPy 中,矩阵实际上是一种特殊的二维数组,因此几乎所有数组的操作都可以应用到矩阵上。不过,矩阵运算与一般的数组运算存在一定的区别,尤其是在点积、乘法等操作中。 1.1 创建矩阵 矩阵可以通过 NumPy 的 array() 函数创建。矩阵的形状可以通过 shape 属性来访问。 import numpy as np# 创建一个 2x3 矩阵mat

正规式与有限自动机例题

答案:D 知识点: 正规式 正规集 举例 ab 字符串ab构成的集合 {ab} a|b 字符串a,b构成的集合 {a,b} a^* 由0或者多个a构成的字符串集合 {空,a,aa,aaa,aaaa····} (a|b)^* 所有字符a和b构成的串的集合 {空,a,b,ab,aab,aba,aaab····} a(a|b)^* 以a为首字符的a,b字符串的集