USACOLongest Prefix

题目来源:http://ace.delos.com/usacoprob2?a=eORCKYsuBVM&S=prefix

水水的DP,水水地过。

定义布尔数组F[],F[i]表示第i个字符的可匹配性,如果能匹配到i,则F[i]为true,否则为false,最后的结果就是f[k]为true时的最大的k。

方程:F[i]=F[i] || F[i-size[j]]   ,其中,size[j]表示第j个单词的长度。

初始化:F[0]=true

程序耗时最可惜的地方是比较匹配串和单词是否相等,这里可以用hash技术,不过这里懒得用了╮(╯_╰)╭

/*
ID:ay27272
PROG:prefix
LANG:C++
*/

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>

using namespace std;

#define MAX_S 200005
#define MAX_N 205

bool f[MAX_S];
int size[MAX_N];
string word[MAX_N];
char s[MAX_S];

bool check(int x,int k)
{
    for (int i=x,j=size[k]-1;j>=0;i--,j--)    //word[]是字符串数组,字符串首位从0开始
        if (word[k][j]!=s[i]) return false;
    return true;
}

int main()
{
    freopen("prefix.in","r",stdin);
    freopen("prefix.out","w",stdout);
    int word_sum=0;
    string tmp;
    cin>>tmp;
    while (tmp!=".")
    {
        word[++word_sum]=tmp;
        size[word_sum]=word[word_sum].size();
        cin>>tmp;
    }

    int sum=0;
    char tmpp;
    while (scanf("%c",&tmpp)!=EOF)
    {
        if (tmpp=='\n') continue;
        s[++sum]=tmpp;
    }

    memset(f,0,sizeof(f));
    f[0]=true;
    int max=0;
    for (int i=1;i<=sum;i++)
    {
        for (int j=1;j<=word_sum;j++)    //这里边的几个优化很重要,不加的话可能TLE
        {
            if (size[j]>i) continue;
            if (!f[i-size[j]]) continue;
            if (!check(i,j)) continue;
            f[i]=true;
            break;
        }
        if (f[i]) max=i;
    }
    cout<<max<<endl;
    return 0;
}
原文地址:https://www.cnblogs.com/ay27/p/2769914.html