sdut 1008 最大公共子串

http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=1008

如果只有两个字符串的话 就直接用DP记忆化搜索  时间复杂度是 两者长度的乘积

这个题也可以DP记忆化搜索 因为所有字符串的的乘积最大为30000 再加上枚举最优 时间复杂度也不大

只要把n维  翻译成一维就可以记忆化了 

不过为了方便 我用了map 来代替记忆化的功能

代码:

#include<iostream>

#include<stdio.h>

#include<string.h>

#include<math.h>

#include<algorithm>

#include<vector>

#include<set>

#include<map>

#include<string>

#include<stack>

#include <iomanip>

using namespace std;

#define LL long long

const int INF=0x3f3f3f3f;

const int N=105;

map<string,int>str;

string s[N];

char a[N];

int I;



bool OK(string k)

{

    for(unsigned int i=1;i<k.size();++i)

    if(s[i][k[i]]!=s[i-1][k[i-1]])

    return false;

    return true;

}

int dp(string k)

{

    map<string,int>:: iterator it;

    it=str.find(k);

    if(it!=str.end())

    return (it->second);

    str[k]=0;

    it=str.find(k);

    if(OK(k))

    {

        it->second=1;

        unsigned int i;

        for(i=0;i<k.size();++i)

        if(k[i]==0)

        break;

        else

        k[i]=k[i]-1;

        if(i==k.size())

        it->second=it->second+dp(k);

    }else

    {

        for(unsigned int i=0;i<k.size();++i)

        {

            if(k[i]>0)

            {

                k[i]=k[i]-1;

                it->second=max(it->second,dp(k));

                k[i]=k[i]+1;

            }

        }

    }

    return (it->second);

}

int main()

{

    for(int i=0;i<N;++i)

    a[i]=i;

    int T;

    cin>>T;

    while(T--)

    {

        int n;

        cin>>n;

        I=0;

        while(n--)

        {

            cin>>s[I];

            if(s[I].size()>0)

            ++I;

        }

        string k;

        for(int i=0;i<I;++i)

        k.insert(k.end(),a[s[i].size()-1]);

        str.clear();

        cout<<dp(k)<<endl;

    }

    return 0;

}

 

你可能感兴趣的:(du)