BZOJ1009 [HNOI2008] GT 시험(KMP 알고리즘 + 행렬 가속 dp)

문자열의 동적 계획:
수험표 번호를 순서대로 처리하고,
f[i][j]를 설정하면 수험표 전 i위 중 후 j위와 불길수의 전 j위상이 동시에 전 i위의 방안수를 나타낸다.
그럼 정답ans=f[n][0]+f[n][1]+...+f[n][m-1]
f[i][j]의 정확한 의미:
1. f[i][j]가 표시하는 모든 방안은 그 후 j위와 관련이 있을 뿐만 아니라 불길한 수를 포함하지 않는다는 것을 보증해야 한다.
2. 중복을 피하기 위해 f[i][j]가 표시하는 모든 방안은 j보다 길이가 크고 불길한 접두사와 같은 접두사를 포함하지 않는다
그렇지 않으면 다음과 같다. 1부터 m 표지, 불길수가 123124일 때 f[i][2]계수 방안에 f[i][5]계수 방안이 포함된 경우
상태 전환:
f[i][j]는 f[i-1][k]만 얻을 수 있으며, i-1위를 채운 후 접미사 k(k로 긴 접미사) 뒤에 num을 한 명 추가하는 것과 같다. 그 다음에 이 i자리의 불길한 접미사와 같은 가장 긴 접미사는 접미사 j이다.
i>=1시: f[i][j]=f[i-1][0]*a[0][j]+f[i-1][1]*a[1][j]]+...+f[i-1][m-1]*a[m-1][j]
예를 들어 불길한 수가 123124라고 가정하면 f[i][3]=f[i-1][2]+f[i-1][5]는 f[i-1][2]의 끝에 있는 ******12는 *12312가 아니기 때문에 f[i-1][5]의 보충이 필요하다.
그러나 불길한 수가 123123이면 f[i][3]=f[i-1][2], f[i][3]의 끝에 있는 *****123은 **123123이 아니기 때문이다.
i==0시: f[0][0]=1, f[0[기타]=0
그 중에서 a[k][j]는 위에서 언급한num에서 몇 개의 값을 얻을 수 있음을 나타내고 kmp 알고리즘으로 미리 처리할 수 있으며 이것은 하나의 행렬이다.
이렇게 하면 무겁지도 빠뜨리지 않고 계산할 수 있다
다시 매트릭스 가속: f[i][j] 구법은 선형 일차 추이식으로 매트릭스로 구성할 수 있다
문제가 있으면 저와 교류하는 것을 환영합니다.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int next[25]={0},hash[155]={0};
char t[25]={0};
int m,mod;
struct juzhen
{
	int s[25][25];
	juzhen()
	{
		memset(s,0,sizeof(s));
	}
};
juzhen A,Z;
juzhen cheng(juzhen A,juzhen B) 
{
	juzhen res;
	int i,j,k;
	for(i=0;i<m;i++)
		for(j=0;j<m;j++)
		{
			for(k=0;k<m;k++)
				res.s[i][j]+=A.s[i][k]*B.s[k][j];
			res.s[i][j]%=mod;
		}
	return res;
}
juzhen ksm(juzhen A,int n)
{
	juzhen res;
	if(n==1) return A;
	res=ksm(A,n/2);
	res=cheng(res,res);
	if(n%2==1) res=cheng(res,A);
	return res;
}
int main()
{
	int n,i,j,sum,ans=0;
	scanf("%d%d%d
",&n,&m,&mod); for(i=1;i<=m;i++) scanf("%c",&t[i]); next[1]=next[2]=1; for(i=2;i<m;i++) { j=next[i]; while(j>1&&t[i]!=t[j]) j=next[j]; if(t[j]==t[i]) next[i+1]=j+1; else next[i+1]=1; } Z.s[0][0]=1;//f[0][0]==1 for(i=0;i<m;i++)// a[][] { j=i+1; sum=A.s[i][j]=1; hash[t[j]]=i+1; while(j!=1) { j=next[j]; if(hash[t[j]]!=i+1) { A.s[i][j]=1; hash[t[j]]=i+1; sum++;// j( 0) } } A.s[i][0]=10-sum;// i 10 , } Z=cheng(Z,ksm(A,n)); for(i=0;i<m;i++) ans+=Z.s[0][i]; printf("%d",ans%mod); return 0; }

좋은 웹페이지 즐겨찾기