您的位置:首页 > 编程语言 > C语言/C++

UVALive 3490(失配 + 解方程)

2015-10-10 16:04 507 查看
本题目的意思:

给定n(n<= 26)用头1-n个大写字母来随机生成串,问要使串中有一个给定的子串(长度不超过12)平均期望的串长。

可以考虑当前d[i]代表在当前随机生成的文本串与模板穿匹配到了i,生成给定的子串的期望长度。

很明显d[i]=sum(d[f[i][k]])/n+1(1<=k<=n);这里的f[i][k]为下一个字符为k那么和模板串的最大匹配。

若用自动机建立是失配边的话,可以直接用他的转移数组。

还有本题目换了老多高斯消元的板子都没有成功,最后还是参考了别人的板子,然而并不知道为什么。

#include <cstring>
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cmath>
using namespace std;
typedef long long ll;
#define rep1(i,x,y) for(int i=x;i<=y;i++)
#define rep(i,n) for(int i=0;i<(int)n;i++)

struct Matrix
{
ll m[15][15];
};
Matrix x;
void gauss(int n)
{
for(int i = 0; i < n; i++)
{
int r = i;
while(r < n && !x.m[r][i]) r++;
if(r != i) for(int j = 0; j <= n; j++) swap(x.m[i][j],x.m[r][j]);
ll tmp = x.m[i][i];
for(int j = i+1; j < n; j++) if(x.m[j][i])
{
ll ha = x.m[j][i];
for(int k = i+1; k <= n; k++)
x.m[j][k] = x.m[j][k]*tmp - x.m[i][k]*ha;
}
}
for(int i = n-1; i >= 0; i--)
{
for(int j = i+1; j < n; j++)
x.m[i]
-= x.m[j]
*x.m[i][j];
x.m[i]
/= x.m[i][i];
}
}
void getfail(char* P,int* f){
int m=(strlen(P));
f[0]=f[1]=0;
for(int i=1;i<m;i++){
int j=f[i];
while(j && P[j]!=P[i]) j=f[j];
f[i+1] = (P[j]==P[i] ? j+1 : 0);
}
}
int n,f[30],a[30][30];
char s[30];
int main()
{
int T,kase=1;
scanf("%d",&T);
while(T--){
memset(a,0,sizeof(a));
scanf("%d %s",&n,s);
int m=(strlen(s));
getfail(s,f);
for(int i=0;i<=m;i++){
if(i==m){
a[i][i]=1; a[i][m+1]=0;
}
else{
a[i][i]=n;
a[i][m+1]=n;
for(int k=0;k<n;k++){
int j = i;
while(j && s[j] != k + 'A') j=f[j];
int ans = (s[j]==k+'A' ? j+1 : 0);
a[i][ans]-=1;
}
}
rep(j,m+2) x.m[i][j]=a[i][j];
}
gauss(m+1);
cout<<"Case "<<kase++<<":\n";
cout<<x.m[0][m+1]/x.m[0][0]<<endl;
if(T) cout<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  algorithm c++ UVA