ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

POJ 1699

2021-07-01 23:34:45  阅读:176  来源: 互联网

标签:const int next ++ POJ dna include 1699


算是一道水题,但是被折腾并不幸多次贡献WA...

太久不写代码略显生疏。思路其实是有的,大体分为两种

第一种是开始尝试的,但就是这里开始不停找不到出路,不明白是何方测评神仙数据卡着,discuss里的有问题的测试数据过的都没问题。思路如下:

  • 之前一道题的练习,领悟到AC自动机本质上是构建了一个很特殊的图,我们寻找这样的字符串的过程,其实可以看做在这个图上旅行的过程,找到一个最短路径,遍历所有点,是的,就变成一个数量级较小的旅行商问题
  • 问题在于重叠的定义,这道题是必须前缀和后缀连接的。所以每当发现当前节点是一个完整匹配串的节点的时候,需要不断利用fail指针回溯找到当前此状态所有可以被自动机完整接受的合法输入串。
  • 这道题妙就妙在虽然是旅行商,但是可以利用状态压缩DP来做,或者状态压缩BFS,只是一直没能调出来,不知道那个神仙数据是什么

第二种其实是一开始方法实践之后想到的,其实方法一绕了远路,与其用AC自动机完整求出,不如直接构造两两输入字符串的“距离”矩阵:

  • 所以思路很明显,先构造距离矩阵
  • 虽然这道题数据量很小,但还是值得思考,寻找有没有快速方法
  • 自己有想过KMP但没实现出来,简单看了下便恍然大悟,非常巧妙的思路,KMP匹配(s在前,t在后),将,s作为目标串,而t作为模式串,就这样一直匹配到s的最后,这是剩余的在t中用作索引的变量就记录了这个长度值,按照一般KMP匹配思路,其实这是一个边角料而已,所以灵活运用就体现在这。
  • 寻路又用到巧妙的状压DP,定义dp(i, j)为在状态i,且最后一个串为j(顺序以输入为准)
#include <iostream>
#include <algorithm>
#include <queue>
#include <string>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <cmath>
#include <string>
#include <stack>
#include <map>
#include <set>
#include <deque>
using namespace std;

const int maxn= 15;
const int maxl= 25;
const int maxs= (1<<10)+5;
const int INF= 0x3f3f3f3f;

int n;
char dna[maxn][maxl];
int bd[maxn][maxn], k_next[maxn][maxl];
int lth[maxn];
int dv[maxs][maxn];

void PreKMP(char *x, int m, int *kmp_next)
{
	int i, j;
	i= 0;
	j= kmp_next[0]= -1;

	while (i< m){
		while (j> -1 && x[i]!= x[j]){
			j= kmp_next[j];
		}

		if (x[++i]== x[++j]){
			kmp_next[i]= kmp_next[j];
		}
		else{
			kmp_next[i]= j;
		}
	}
}
int CalcOver(int s, int t)
{
	int i, j;
	i= j= 0;
	while (1){
		while (j> -1 && dna[s][i]!= dna[t][j]){
			j= k_next[t][j];
		}
		++i;
		++j;
		if (i>= lth[s]){
			break;
		}
		if (j>= lth[t]){
			j= k_next[t][j];
		}
	}

	return j;
}

int main(int argc, char const *argv[])
{
	int kase= 0;
	scanf("%d", &kase);

	while (kase--){
		scanf("%d", &n);
		for (int i= 0; i< n; ++i){
			scanf(" %s", dna[i]);
			lth[i]= strlen(dna[i]);
			PreKMP(dna[i], lth[i], k_next[i]);
		}

		for (int i= 0; i< n; ++i){
			for (int j= 0; j< n; ++j){
				if (i== j){
					bd[i][j]= lth[i];
				}
				else{
					bd[i][j]= CalcOver(i, j);
				}
			}
		}

		const int e_mk= (1<<n)-1;
		for (int i= 0; i<= e_mk; ++i){
			for (int j= 0; j< n; ++j){
				dv[i][j]= INF;
				if (i & (1<<j)){
					if (0== (i ^ (1<<j))){
						dv[i][j]= lth[j];
					}
					else{
						int ii= i ^ (1<<j);
						for (int k= 0; k< n; ++k){
							if (ii & (1<<k)){
								dv[i][j]= min(dv[i][j], dv[ii][k]+lth[j]-bd[k][j]);
							}
						}
					}
				}
			}
		}
		int ans= INF;
		for (int i= 0; i< n; ++i){
			ans= min(ans, dv[e_mk][i]);
		}

		printf("%d\n", ans);
	}
	return 0;
}

标签:const,int,next,++,POJ,dna,include,1699
来源: https://www.cnblogs.com/Idi0t-N3/p/14961374.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有