单词

小y有n个长度为m,且只含x,y,z的单词,给定相似度的定义:两个单词相同位相同的字母数

d=∑[Ai==Bi]

求相似度为0~m的单词对有多少个

注意:(x,y)=(y,x)不考虑(x,x)

输入:

n m

n个长度为m的单词

输出:

m+1行

第i行表示相似度为i-1时,单词对数

样列输入:

4 3

xyz

xyz

zzx

xzz

输出:

2

1

2

1

范围:n*m<=100000

(分类讨论)暴力+dp

n*m<=100000所以n大m就小,m大n就小

m>=12时,n小直接枚举区间暴力判断

m<=12时,我们用状压dp

用0表示x,1表示y,2表示z

用3进制数表示

f[s][p]表示状态为s,相似度为p的对数

每一次修改状态中一个数

f[s'][p-1]+=f[s][p];

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 using namespace std;
 6 typedef long long ll;
 7 ll pw[15],f[550001][13],ff[550001][13],ans[100001];
 8 ll s[550001];
 9 int n,m;
10 char str[100001];
11 void work1()
12 {int i,j,p,l;
13     for (i=1; i<=n; i++)
14     {int now=0;
15         for (j=1; j<=m; j++)
16         {
17             now*=3;
18                 char ch=getchar();
19                 while (ch<'x'||ch>'z') ch=getchar();
20             now+=ch-'x';
21         }
22       s[now]++;
23     }
24     pw[0]=1;
25       for (i=1;i<=m;i++) pw[i]=pw[i-1]*3;
26       for (i=0;i<pw[m];i++) ff[i][m]=s[i];
27       for (i=0;i<m;i++)
28       {memcpy(f,ff,sizeof(f));
29            for (j=0;j<pw[m];j++)
30            {
31                ll s1=j/pw[i]%3,s2=j-s1*pw[i];
32                for (p=0;p<=2;p++)
33                if (p!=s1)
34             {
35                    for (l=m-i;l<=m;l++) f[s2+p*pw[i]][l-1]+=ff[j][l];
36                }
37            }
38            memcpy(ff,f,sizeof(f));
39       }
40       for (i=0;i<pw[m];i++)
41       {
42           for (j=0;j<=m;j++)
43            ans[j]+=s[i]*ff[i][j];
44       }
45       ans[m]-=n;
46     for (i=0;i<=m;i++) ans[i]/=2;
47 }
48 void work2()
49 {int i,j,l;
50     for (i=0; i<n*m; i++)
51     {
52         char ch=getchar();
53         while (ch<'x'||ch>'z') ch=getchar();
54         str[i]=ch;
55     }
56     for (i=0; i<n; i++)
57         for (j=0; j<i; j++)
58         {
59             int cnt=0;
60             for (l=0; l<m; l++)
61                 if (str[i*m+l]==str[j*m+l])
62                     cnt++;
63             ans[cnt]++;
64         }
65 }
66 int main()
67 {int i;
68     cin>>n>>m;
69     if (m<=12) work1();
70     else work2();
71     for (i=0; i<=m; i++)
72         printf("%lld\n",ans[i]);
73 }

 

posted @ 2017-09-28 20:29  Z-Y-Y-S  阅读(484)  评论(0编辑  收藏  举报