高明的最长公共子序列

国家集训队论文。?

https://wenku.baidu.com/view/ed99e4f77c1cfad6195fa776.html

XJOI题 重复串。 虽然不满的1000^3复杂度能水过,但还是学了一下。。

以后压位别压太死了(用unsigned压32位这种),可能会引出很多麻烦,比如自然溢出之类的。。

放代码。

 1 #include <bits/stdc++.h>
 2 #define U unsigned
 3 #define ll long long
 4 const U h=2147483648;
 5 using namespace std;
 6 U g[26][34],u[34],X[34],H[32];
 7 int n,o,mx,f[65536]; char S[1005];
 8 int main(){
 9     scanf("%d%s",&n,S+1);
10     H[0]=1; for (int i=1;i<32;++i) H[i]=H[i-1]<<1;
11     for (int i=1;i<65536;++i) f[i]=f[i>>1]+(i&1);
12     for (int I=1;I<=n;++I){
13         memset(g,0,sizeof g); memset(u,0,sizeof u);
14         for (int i=I,j=0;i<=n;++i,++j) g[S[i]-'a'][j>>5]|=H[j&31];
15         for (int k=1;k<I;++k){
16             o=S[k]-'a';
17             for (int i=0;i<34;++i) X[i]=u[i]|g[o][i];
18             for (int i=33;~i;--i) u[i+1]|=(bool)(u[i]&h),u[i]<<=1;
19             u[0]|=1; o=n-I+2; X[o>>5]|=H[o&31];
20             (u[o>>5]|=H[o&31])^=H[o&31];
21             for (int i=0,j=0;i<34;++i)
22                 if ((ll)X[i]<(ll)u[i]+j) u[i]=X[i]-u[i]-j,j=1;
23                 else u[i]=X[i]-u[i]-j,j=0;
24             (u[o>>5]|=H[o&31])^=H[o&31];
25             (X[o>>5]|=H[o&31])^=H[o&31];
26             for (int i=0;i<34;++i) (u[i]^=X[i])&=X[i];
27         }
28         o=0;
29         for (int i=0;i<34;++i) o+=f[u[i]&65535]+f[u[i]>>16];
30         mx=max(mx,o);
31     }
32     printf("%d\n",n-mx*2);
33     return 0;
34 }
Victor Hugo

 

posted @ 2017-09-19 17:25  cyz666  阅读(133)  评论(0编辑  收藏  举报