【POJ 1699】 Best Sequence(KMP+状压DP)
| Time Limit: 1000MS | Memory Limit: 10000K | |
| Total Submissions: 5594 | Accepted: 2206 |
Description

Input
Output
Sample Input
1 5 TCGG GCAG CCGC GATC ATCG
Sample Output
11
Source
题目大意:T组输入,对于每组输入先是一个正整数n,之后跟着n个串,每个串长度1~20不等。
问把这n个串串成一个长串至少需要多少个字符,连接方式可以是a串后缀与b串前缀相同时叠加方式连接。
由于串很少,可以想到状压,开一个二维的dp数组,第一位用二进制表示已连进的串,第二维表示以某串做结尾,这样dp数组就可以表示任何一种状态的最少字符消耗
对于转移暴力好像也可过,用了个kmp 一发WA 因为会有子串的问题,当新加入的串是结尾串的子串的时候,更新的dp数组应该是以原本的结尾串为结尾的位置。
代码如下:
#include <iostream>
#include <cmath>
#include <vector>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <queue>
#include <stack>
#include <list>
#include <algorithm>
#include <map>
#include <set>
#define LL long long
#define Pr pair<int,int>
#define fread() freopen("in.in","r",stdin)
#define fwrite() freopen("out.out","w",stdout)
using namespace std;
const int INF = 0x3f3f3f3f;
const int msz = 10000;
const int mod = 1e9+7;
const double eps = 1e-8;
int Next[23][23];
int len[23];
char str[23][33];
int dp[(1<<10)][10];
int n;
void GetNext(int pos)
{
int i,j;
i = 0;
j = Next[pos][0] = -1;
while(i < len[pos])
{
while(j != -1 && str[pos][j] != str[pos][i]) j = Next[pos][j];
++i,++j;
Next[pos][i] = j;
}
}
int get(int a,int b)
{
int i,j;
i = j = 0;
while(i < len[a])
{
while(j != -1 && str[b][j] != str[a][i]) j = Next[b][j];
++j,++i;
if(j == len[b]) return 0;
}
return len[b]-j;
}
int main()
{
//fread();
//fwrite();
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i = 0; i < n; ++i)
{
scanf("%s",str[i]);
len[i] = strlen(str[i]);
}
memset(dp,INF,sizeof(dp));
for(int i = 0; i < n; ++i)
{
GetNext(i);
dp[1<<i][i] = len[i];
}
int tot = 1<<n;
for(int i = 0; i < tot; ++i)
for(int j = 0; j < n; ++j)
if(i&(1<<j))
for(int k = 0; k < n; ++k)
{
if(i&(1<<k)) continue;
int tmp = get(j,k);
if(tmp) dp[i+(1<<k)][k] = min(dp[i+(1<<k)][k],dp[i][j]+get(j,k));
else dp[i+(1<<k)][j] = min(dp[i+(1<<k)][j],dp[i][j]);
}
int ans = INF;
for(int i = 0; i < n; ++i)
ans = min(ans,dp[tot-1][i]);
printf("%d\n",ans);
}
return 0;
}
【POJ 1699】 Best Sequence(KMP+状压DP)
原文:http://blog.csdn.net/challengerrumble/article/details/50838581