又到一年校赛时。。转眼已经大四。
奇葩的学校,校赛是个人赛。。其实我挺喜欢个人赛。
但是作为一个老掉牙的老队员,还没拿过校赛一等奖。。。。
好吧,刷刷水题恢复手感。
这是一个简单的题目,给出两个串,求最长公共子串。只不过串中的字符是一个个单词。
把单词用map转化为数字就成为我们熟悉的问题了!
再用DP轻松解决公共子串问题,用一个fa数组保存输出的顺序。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
using namespace std;
map<string,int> mp;
int sv1[210],sv2[210],f[210],fa[210];
string svw[210];
int main(){
//freopen("2250out.txt","w",stdout);
int l,flag,fi,l1,l2,totwords,ma,mj,tmp,i,j;
char s[200];
string str;
flag=0;
while(1){
if (flag==1) break;
mp.clear();
totwords=0;
l1=l2=0;
while(1){
if (scanf("%s",s)==EOF) {flag=1;break;}
l=strlen(s);
if (s[0]=='#'&&l==1) break;
str=s;
if (mp[str]==0) {mp[str]=++totwords;svw[totwords]=str;}
sv1[++l1]=mp[str];
}
if (flag==1) break;
while(1){
scanf("%s",s);
str=s;
l=strlen(s);
if (s[0]=='#'&&l==1) break;
if (mp[str]!=0){
sv2[++l2]=mp[str];
}
}
//以上预处理
//然后dp
memset(f,0,sizeof(f));
memset(fa,-1,sizeof(fa));
for(i=1;i<=l1;++i){
ma=0;
mj=-1;
for(j=1;j<=l2;++j){
tmp=f[j];
if (sv1[i]==sv2[j]&&ma+1>f[j]){
f[j]=ma+1;
fa[j]=mj;
}
if (tmp>ma) {
ma=tmp;
mj=j;
}
}
}
//输出
ma=0;
for(i=1;i<=l2;++i){
if (f[i]>ma) {ma=f[i];tmp=i;}
}
l1=0;
while(tmp!=-1){
sv1[++l1]=sv2[tmp];
tmp=fa[tmp];
}
fi=0;
for(i=l1;i>=1;--i){
if (fi==0) fi=1;
else putchar(' ');
printf("%s",svw[sv1[i]].c_str());
}
printf("\n");
}
return 0;
}