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;
}