状压DP+套路转化DP式将复杂度转化为与n,m中较小的一维上。
注意,作死不写哈希而将字符串看做26进制数的做法是错误的,
因为这样就把a字母看做前导零了,在数学中可能不碍事,但是在字符串比较中就会直接爆炸。
所以:一个字母表达的数字为 ch-'a'+1,用27进制。
ACcode:
#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#define maxn 1000005
#define LL long long
using namespace std;
int n,c[20];
char s[20];
LL item[20],Pow[20];
int dp[150][(1<<15)-1],seq[maxn],Len,pre[20],nxt[maxn][20];
bool cmp(const int &a,const int &b)
{
return item[a]<item[b];
}
int main()
{
scanf("%d",&n);
Pow[0]=1;
for(int i=1;i<=12;i++) Pow[i]=Pow[i-1]*27;
for(int i=0;i<n;i++)
{
scanf("%s",s);
for(int j=0,len=strlen(s);j<len;j++)
item[i]+=(s[j]-'a'+1)*Pow[j];
c[i]=i;
}
sort(c,c+n,cmp);
int loc,ans=0x3f3f3f3f,m,siz;
LL num;
scanf("%d",&m);
for(int tim=1;tim<=m;tim++)
{
memset(dp,0x3f,sizeof dp);
dp[0][0]=0;
Len=0;
scanf("%d",&siz);
for(int j=1;j<=siz;j++)
{
scanf("%s",s);num=0;
for(int k=0,len=strlen(s);k<len;k++)
num+=(s[k]-'a'+1)*Pow[k];
int L=0,R=n-1,Mid;
while(L<R)
{
Mid=(L+R+1)>>1;
if(item[c[Mid]]<=num) L=Mid;
else R=Mid-1;
}
if(item[c[L]]==num)
seq[++Len]=c[L];
}
memset(pre,-1,sizeof pre);
for(int i=Len;i>=0;i--)
{
for(int j=0;j<n;j++) nxt[i][j]=pre[j];
pre[seq[i]]=i;
}
for(int i=0,sta;i<=n*(n-1)/2;i++)
for(sta=0;sta<1<<n;sta++)
if(dp[i][sta]<0x3f3f3f3f)
for(int k=n-1,cnt=0;k>=0;k--)
if(!(sta & (1<<k)))
{
if(nxt[dp[i][sta]][k]!=-1)
dp[i+cnt][sta|(1<<k)]=min(dp[i+cnt][sta|(1<<k)],nxt[dp[i][sta]][k]);
}
else cnt++;
for(int i=0;i<=n*(n-1)/2;i++)
if(dp[i][(1<<n)-1]<0x3f3f3f3f)
{
if(i<ans)
{
ans=i;
loc=tim;
}
break;
}
}
if(ans==0x3f3f3f3f) puts("Brand new problem!");
else
{
printf("%d\n",loc);
printf("[:");
for(int i=1;i<=n*(n-1)/2-ans+1;i++) putchar('|');
printf(":]");
}
}