萌萌哒的初学者poj终于做满100题了,可惜这题不是靠自己的能力过的,因为看到这个单词串,实在是想不出状态转移方程呢。
参考了下百度还是很快理解的,从字符串的尾巴开始递推,字符串是0-L-1,设d[L]=0;
d[i]=d[i+1]+1;这是第一个转移方程,是最坏情况,不能匹配,然后移除这个字符
d[i]=min(d[i],d[pd]+pd-i-len),这个是可以匹配的情况,如果i位置的字符和单词的首字母相同,就设pd从i开始扫描,pm从单词开始扫描,如果相同就都+1,如果不同就pd+1,如果pd=L了就是超出范围了,匹配失败,如果pm=len就是匹配成功,然后这会就是从d[pd]开始了,加上中间为了匹配这个单词而移除的字符数就是pd-i-len。
看来我的dp基础还是很薄弱,明天继续刷dp,刷大小白,状压先放一放了。
#include<iostream> #include<cstdio> #include<cctype> #include<cstdlib> #include<cmath> #include<algorithm> #include<cstring> #include<string> #include<vector> #include<queue> #include<map> #include<set> #include<sstream> #include<stack> using namespace std; #define MAX 105 typedef long long LL; const double pi=3.141592653589793; const int INF=1e9; const double inf=1e20; const double eps=1e-6; char c[605][28]; int main(){ int w,l; char s[305]; int d[305]; scanf("%d%d",&w,&l); getchar(); scanf("%s",s); for(int i=0;i<w;i++){ getchar(); scanf("%s",c[i]); } d[l]=0; int flag=0; for(int i=l-1;i>=0;i--){ d[i]=d[i+1]+1; for(int j=0;j<w;j++){ int len=strlen(c[j]); if(c[j][0]==s[i]&&len<=l-i){ int pd=i+1,pm=1; while(pd<l){ if(s[pd]==c[j][pm]){ pm++; pd++; } else pd++; if(pm==len){ d[i]=min(d[i],d[pd]+pd-i-len); break; } } } } } printf("%d\n",d[0]); return 0; }