一个dp问题的解法

Felicia's life问题描述: 有一天,Felicia收到公司发的一篇文章,文章很长,而且全是英文。不过这不要紧,要命是是,上司要她找出文章里重复出现过的内容,并且要找出最长的长度。要是那篇文章是很短的话,那也没所谓,问题就是这篇文章太长了,你能帮帮她吗? 输入:多组测试数据,一行为一组数据,每行为一个字符串,串长小于1000输出:对每组数据输出最长的重复出现的串的长度。 样例输入: abcabc abababab abcdefg qqqqqqqqqq abcdefghiabcefgfghiabd 样例输出: 3 4 0 5 6 解法: 第一个即是简单暴力搜索:
#include<iostream>

#include<string>



using namespace std;



char inp[1001];

int l[1001],ma=1,d[1001];

//string inp;



int main()

{

	int le;

	while(scanf("%s",inp)!=EOF)

	{

		le=0;

		while(inp[le]!='/0') le++;

		ma=le/2;

		//if(le%2!=0) max++;

		for(;ma>=1;ma--)

		{

			for(int i=0;i<=le-ma*2;i++)

			{

				for(int j=i+ma;j<=le-ma;j++)

				{

					for(int k=0;k<ma;k++)

					{

						if(j+k>=le||inp[i+k]!=inp[j+k])

							goto next;

					}

					cout<<ma<<endl;

					goto end;

next:;

				}

			}

		}

		cout<<"0"<<endl;

end:;

	}

}
从可能最长的重复内容向下搜索。遇到满足的情况就直接给出结果。 但是显然会TLE。 第二个dp方法:
#include<stdio.h>

#define MAX_LONG  1000

long num[MAX_LONG];

int main()

{

    long n1, n2, nl;

    char c1[MAX_LONG];

    char c;

    long *p1=num;

    while( scanf("%s", c1) != EOF )

    {

        long nMax = 0;

        for(nl=0;c1[nl];nl++)

            ;

        p1[0]=0;c=*c1; //init

        for(n2=1;c1[n2];n2++) //初始化,和第一个字符做比较。

        {

            if(c1[n2]==c)

            {

                p1[n2]=1;

            }

            else

            {

                p1[n2]=0;

            }

        }

        for(n1=1;c=c1[n1];n1++)  //dp

        {

            p1[n1]=0;

            for(n2=nl-1;n2>n1;n2--) //对于n1后面的字符搜索

            {

                if(c1[n2]==c) //如果和n1相同 

                {

                    p1[n2]=p1[n2-1]+1; //则这个字符串的长度+1

                    if(p1[n2]>n2-n1)p1[n2]=n2-n1; //这个字符串一定在n2和n1之间

                    else if(p1[n2]>nMax)nMax=p1[n2]; 

                }

                else //如果和当前比较的字符不同,则重新开始计算。

                {

                    p1[n2]=0;

                }

            }

        }

        printf("%d/n", nMax);

    }

    return 0;

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值