Description
Input
Output
R行,每行一个实数表示答案
Sample Input
9 3
A1 B2 C3 D4 E5 D4.0 C3.0 B2.0 A1.0[nya]
3 A1 A1.0 E5[qwerty]
5 B1{poi} B2 C3 A2 A1
7 C3 D4 E5 D4.0 C3.0 B2.0 A1.0[nyanya]
Sample Output
0.666667
0.400000
1.000000
Data Constraint
Hint
Solution
这题输入比较麻烦
不过我大C++直接输入就行了,什么判断都不用
题目保证第一个乐谱每个字符串只会出现一次,那就用hash(map)把它存好,然后分别匹配做最长公共子序列即可
Code
#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define N 20
#define L 201000
#define M 10100000
#define ll long long
using namespace std;
int a[2][L],d[L],h[M],b[2][M],n,m;
ll E[8];
int hash(char s[N],int l)
{
ll x=s[1]-65;
x=x*E[6]*8ll;
ll y=s[2]-49;
y=y*E[6];
if(l>3)
{
fo(j,4,l)
{
y=y+E[9-j]*(ll)(s[j]-47);
}
}
y+=x;
int z=y%M;
while(h[z]!=0&&h[z]!=y) z=(z+1)%M;
h[z]=y;
return z;
}
void work(int jy)
{
if(jy==1) scanf("%d",&m);
char s[N];
fo(i,1,m)
{
scanf("%s ",s+1);
int l=strlen(s+1);
if(s[l]==']'||s[l]=='}'||s[l]==')'||s[l]=='>')
{
while(s[l]!='['&&s[l]!='{'&&s[l]!='('&&s[l]!='<') l--;
l--;
}
int x=hash(s,l);
a[jy][i]=x;b[jy][x]=i;
}
}
int get(int jy)
{
int l=0,r=d[0];
while(l+1<r)
{
int m=(l+r)/2;
if(d[m]<jy) l=m;else r=m;
}
if(d[r]<jy) l=r;return l;
}
int main()
{
int ac;scanf("%d%d\n",&n,&ac);
E[0]=1;fo(i,1,6) E[i]=E[i-1]*11ll;
m=n;work(0);
for(;ac;ac--)
{
work(1);
memset(d,0,sizeof(d));
fo(i,1,m)
{
int x=a[1][i];
if(b[0][x]==0) continue;
x=b[0][x];
if(d[d[0]]<x) d[++d[0]]=x;
else
{
int y=get(x);
d[y+1]=x;
}
}
printf("%.6lf\n",d[0]*1.0/m);
}
}