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