xtu-1265 Longest Common Subsequence(字符串/计数)
Longest Common Subsequence |
||
Accepted : 11 | Submit : 105 | |
Time Limit : 3000 MS | Memory Limit : 65536 KB |
Longest Common SubsequenceBobo has a sequence A=(a 1 ,a 2 ,…,a n ) of length n . He would like to know f(0),f(1),f(2) and f(3) where f(k) denotes the number of integer sequences X=(x 1 ,x 2 ,x 3 ) where:
Note:
InputThe input contains zero or more test cases and is terminated by end-of-file. For each case, The first line contains two integers n,m . The second line contains n integers a 1 ,a 2 ,…,a n .
OutputFor each case, output four integers which denote f(0),f(1),f(2),f(3) . Sample Input3 3 1 2 2 5 3 1 2 3 2 1 Sample Output1 14 11 1 0 1 17 9 NoteFor the second sample, X=(3,3,3) is the only sequence that the length of longest common subsequence of A and X is 1 . Thus, f(1)=1 . |
A中只要ai>m则舍去,因为X取不到ai。设A中一共有cnt种元素,那么还剩m-cnt个元素没有。
枚举x1,x2,x3的值∈[1,cnt+1],其中cnt+1表示x取A中不存在的值。预处理出nxt[i][c],表示第i个元素后,元素c是出现在第几个位置。
枚举集合(x1,x2,x3)的子集,找出是A的子序列的最大子集,如果xi不在这个子集中且xi的取值为cnt+1,那么方案数*(m-cnt)
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MX = 1e6 + 5;
int vis[MX], a[205], sz, cnt;
int nxt[205][205], t[5], st[5];
LL f[5];
int solve(int len) {
if(len == 0) return 1;
int i = 0, index;
for(index = nxt[0][st[i]]; index > 0 && i < len;) {
index = nxt[index][st[++i]];
}
if(i==len) return 1;
return 0;
}
int S, mx;
void dfs(int len, int i, int sta) {
if(i > 2) {
if(solve(len) && mx < len) {
S = sta;
mx = len;
}
} else {
dfs(len, i + 1, sta);
st[len] = t[i];
dfs(len + 1, i + 1, sta | (1 << i));
}
}
int main() {
int n, m;
while(~scanf("%d%d", &n, &m)) {
memset(vis, 0, sizeof(vis));
memset(nxt, -1, sizeof(nxt));
memset(f, 0, sizeof(f));
for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
sz = cnt = 0;
for(int i = 1; i <= n; i++) {
if(a[i] <= m) {
a[++sz] = a[i];
if(vis[a[sz]]) a[sz] = vis[a[sz]];
else {
vis[a[sz]] = ++cnt;
a[sz] = vis[a[sz]];
}
}
}
for(int i = 0; i <= sz; i++) {
for(int j = i + 1; j <= sz; j++) {
if(nxt[i][a[j]] == -1) nxt[i][a[j]] = j;
}
}
for(int i = 1; i <= cnt + 1; i++) {
for(int j = 1; j <= cnt + 1; j++) {
for(int k = 1; k <= cnt + 1; k++) {
t[0] = i; t[1] = j; t[2] = k;
S = mx = 0;
dfs(0, 0, 0);
LL tmp = 1;
for(int s = 0; s < 3; s++) {
if((S & (1 << s))==0&&t[s] == cnt + 1) {
tmp *= (LL)(m - cnt);
}
}
f[mx] += tmp;
}
}
}
printf("%lld %lld %lld %lld\n", f[0], f[1], f[2], f[3]);
}
return 0;
}
上一篇: HDU-6314 Matrix(计数)
下一篇: 素数筛选法