Beyond the Void
BYVoid
USACO 2.3.1 Longest Prefix 最长前缀

动态规划题,要扫描比较字符串

定义dp[i]为串S中从第i位开始的串的最长前缀的长度,根据题目要求,结果输出 dp[0] (从第0位开始到len(S)-1的串的最长前缀的长度)

定义fd(i)为//主串S中以第i位开始的字串,向后比较匹配集合中元素的最大长度

倒序递推: 从i=lens-1 到 i=0

  • fd(i)=0
  • dp [i]=0
  • fd(i)=k(k>0)
  • dp [i]=dp[i+j]+j (1<=j<=k-1;dp[i+j]!=0)
  • 如果不满足上式dp [i]=dp[i+k]+k
/*
ID: cmykrgb1
PROG: prefix
LANG: C++
*/
#include <stdio.h>
#include <string.h>
#define maxl 200201
FILE *fi,*fo;

typedef struct
{
	char w[11];
	int len;
} dic;

dic p[201];
char s[maxl];
long int lenp,lens;
long int dp[maxl];

void readfile(void)
{
	char c,lc=0;
	int i=0,j=0;
	while ((c=getc(fi))!='.')
	{
		if (c>='A' && c<='Z')
		{
			if (!(lc>='A' && lc<='Z'))
				i++;
			p[i].w[j++]=c;	
		}
		else 
			if (p[i].len==0)
			{
				p[i].len=j;
				j=0;
			}
		lc=c;
	}
	lenp=i;
	j=0;
	while ((c=getc(fi))!=EOF)
		if (c>='A' && c<='Z')
			s[j++]=c;
	lens=j;
	fclose(fi);
}

long int fd(long int k) //从第k位开始向后比较p[*].len位判断有无匹配
{
	int i,j;
	for (j=lenp;j>=1;j--)
	{
		if (p[j].w[0]==s[k])
		{
			for (i=1;i<=p[j].len-1;i++)
				if (p[j].w[i]!=s[k+i])
					goto next;
			return p[j].len;
		}
next:;
	}
	return 0;
}

void dynamic(void)
{

	long int i,j,k;
	dp[lens-1]=fd(lens-1);
	for (i=lens-2;i>=0;i--)
	{
		k=fd(i);
		if (k==0)
			dp[i]=0;
		else
		{
			if (dp[i+1]==0)
			{
				for (j=2;j<=k-1;j++)
					if (dp[i+j]!=0)
					{
						dp[i]=dp[i+j]+j;
						goto next2;
					}
				dp[i]=dp[i+k]+k;
			}
			else
				dp[i]=dp[i+1]+1;
		}
next2:;
	}
}

void ssort(void)
{
	int i,j,min,m;
	char tstr[10];
	for (i=1;i<=lenp-1;i++)
	{
		min=11;
		for (j=i+1;j<=lenp;j++)
			if (p[j].len<min)
			{
				min=p[j].len;
				m=j;
			}
		if (p[i].len>p[m].len)
		{
			strcpy(tstr,p[i].w);
			strcpy(p[i].w,p[m].w);
			strcpy(p[m].w,tstr);
			min=p[i].len;
			p[i].len=p[m].len;
			p[m].len=min;
		}
	}
}

int main(void)
{
	fi=fopen("prefix.in","r");
	fo=fopen("prefix.out","w");
	readfile();
	ssort();
	dynamic();
	fprintf(fo,"%ldn",dp[0]);
	fclose(fo);
	return 0;
}

上次修改时间 2017-02-03

相关日志