CF 79CBeaver DP 字符串

主要方法转自http://http://blog.csdn.net/struggle_mind/article/details/8038328 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#define eps 1e8
#define LMT 100003
using namespace std;
char str[LMT],word[LMT];
int ppos[LMT],far[LMT],dp[LMT],len,llen;
//要记得的是子串一定有一个起点,若无法确定,就贪心一下,取个最远的
int main()
{
    int n,ans,pos,pre;
    scanf("%s",str);
    len=strlen(str);
    scanf("%d",&n);
    for(int i=0;i<len;i++)far[i]=eps;
    while(n--)
    {
        scanf("%s",word);
        llen=strlen(word);
        for(int i=0;i+llen<=len;i++)//单词很短,所以只需要用暴力的手法
        {
            int t;
            for( t=0;t<llen;t++)
            if(str[i+t]!=word[t])break;
            if(t>=llen)far[i+llen-1]=min(far[i+llen-1],llen);
        }
    }/*求已这个字母结尾的最短字符串
	 这样可以算出符合题意的字串的最远起点
	 只所以要取最短是为了防止起点中也包括了无聊单词
	 */
    dp[0]=(far[0]==eps);
    ans=dp[0];pre=pos=0;
    for(int i=1;i<len;i++)
    {
           if(far[i]>i-pre+1) dp[i]=dp[i-1]+1;
           else
           {
               dp[i]=min(far[i]-1,i-pre);pre=max(pre,i-far[i]+2);
			   /*
			   一开始是想选择i-far[i]+1的,可是i-far[i]+1可能正是现在的pre,
			   pre是已贪心思维确定的子串起点
			   */
           }
           if(ans<dp[i]) ans=dp[i],pos=i-dp[i]+1;
    }
            printf("%d %d\n",ans,pos);
    return 0;
}



你可能感兴趣的:(CF 79CBeaver DP 字符串)