C:BM(Berlekamp-Massey)算法

伯利坎普-梅西算法(Berlekamp-Massey)

百度百科:Berlekamp-Massey算法可以找到给定二进制输出序列的最短线性反馈移位寄存器(LFSR)。 该算法还将在任意场中找到线性递归序列的最小多项式。

算法原理

(跟网上流传的原理方法有些不同)
在这里插入图片描述

算法流程

在这里插入图片描述

我的思路

我认为这种算法的主要难度在于给定或已算出的f i (x)对a(i+1)的计算,参考思路如下:
在这里插入图片描述
当然这也是最直接暴力的思路,仅供参考

程序代码

数组长度均为可调

输入

不超过数组长度的二进制序列,如0111010101(乱打的

输出

最短LFSR的特征多项式 f(x),次数由高到低排列

#include<stdio.h>
int cb(int f,int a[],int n)//f以二进制表示系数 
{
	if(f==1) return 0;
	int c[30],i,k,b=0;
	i=0;
	while(f!=0)//f对应的系数序列c[] 
	{
		c[i]=f%2;
		f=f/2;
		i++;
		c[i]=-1;
	}
	k=i-2;//c1.place
	while(k>=0)//计算a~ 
	{
		b=b+c[k]*a[n-1];
		n--;
		k--;
	}
	return b%2;
}
int cpl(int l[],int n)//compare l[]
{
	int i;
	for(i=n;i>=0;i--)
	{
		if(i==0) return n;//all equal
		if(l[i]>l[i-1]) return i-1;//return m
	}
}
int pow(int m,int n)
{
	int s=1;
	while(n!=0)
	{
		if(n&1) s*=m;
		m*=m;
		n>>=1;
	}
	return s;
}
int cfn(int fm,int fn)//计算f[n+1] 
{
	int cm[30],cn[30],i,s;
	for(i=0;i<30;i++)
	{
		cm[i]=0;
		cn[i]=0;
	}
	i=0;
	while(fm!=0)
	{
		cm[i]=fm%2;
		fm=fm/2;
		i++;
	}
	i=0;
	while(fn!=0)
	{
		cn[i]=fn%2;
		fn=fn/2;
		i++;
	}
	for(i=0;i<30;i++) cn[i]=(cm[i]+cn[i])%2;//序列对应系数相加后模2 
	s=0;
	for(i=0;i<30;i++) if(cn[i]==1) s+=pow(2,i);
	return s;
}
int max(int a,int b)
{
	if(a>b) return a;
	return b;
}
int main()
{
	char a_str[30];
	int a[30],f[30],l[30],b[30],i=0,len,n,m,d;//max length = 30
	f[0]=1;l[0]=0;
	printf("二进制序列:");
	scanf("%s",a_str);
	while(a_str[i]!='\0') 
	{
		a[i]=a_str[i]-'0';
		i++;
	}
	len=i;
	for(n=0;n<len;n++)
	{
		if(a[n]==cb(f[n],a,n))//f[n]能生成a的前n+1位 
		{
			f[n+1]=f[n];
			l[n+1]=l[n];
		}
		else//不能生成 
		{
			if(cpl(l,n)==n)//l0=l1=...=ln 
			{
				f[n+1]=pow(2,n+1)+1;
				l[n+1]=n+1;
			}
			else
			{
				m=cpl(l,n);//lm<lm+1=...=ln
				d=(m-l[m])-(n-l[n]);
				if(d>=0) f[n+1]=cfn(f[n],(f[m]<<d));//m-lm ≥n-ln 
				else
				{
					d=-1*d;//n-ln>m-lm
					f[n+1]=cfn((f[n]<<d),f[m]);
				}
				l[n+1]=max(l[n],n+1-l[n]);
			}
		}
	}
	int s=f[n],c[30],k,q;
	i=0;
	while(s!=0)
	{
		c[i]=s%2;
		s=s/2;
		i++;
		c[i]=-1;
	}
	k=i-1;
	for(i=0;i<=k;i++) if(c[i]==1) break;
	q=i;
	printf("最短LFSR的特征多项式 f = ");
	for(i=k;i>=q;i--)
	{
		if(c[i]==1&&i!=q)
		{
			if(i!=1) printf("x^%d + ",i);
			else printf("x + ");
		}
		else if(i==q)
		{
			if(q!=0)
			{
				if(i!=1) printf("x^%d",i);
				else printf("x");
			}
			else printf("1");
		}
	}
	return 0;
}

原理和流程都是比较简单的,就是C语言写的有点多(或者大概率是我菜
用python的话就不用考虑数组长度和整型数大小(C也有一个Miracl库可以实现大数
python实现请移步隔(不记得哪的)壁

函数说明
cb():计算a’,即通过已知的多项式f(x)求出相应的a以用于与输入的二进制序列比较
cpl():比较l[ ]中的每一个数值,在不能生成前n+1位时使用,返回值为次小值的最大下标,若无次小值,返回当前可生成的位数n
pow():快速指数运算
cfn():在不能生成前n+1位时用于计算f[n+1]


版权声明:本文为qq_33439662原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。