POJ 2004 Mix and Build (预处理+dfs)
题意:
给N个字符串,要求出一个序列,在该序列中,后一个串,是由前一个串加一个字母后得来的(顺序可以改动)。
问最多能组成多长的序列。
思路:将给的字符串排序,再对所有的字符串按长度从小到大排序,若长度相同,则按字典序排。
然后找出符合条件的字符串A和B(即B可由A加一个字母得来),建立边的关系。
之后对所有根节点进行dfs深搜,如果当前的长度大于目前的maxlen,则更新,同时记录前驱节点。
最后根据前驱节点,输出路径即可。
#include <stdio.h>
#include <map>
#include <string.h>
#include <algorithm>
#include <string>
#include <queue>
#include <vector>
#include <iostream> using namespace std;
const int maxn=;
int n=;
vector<int>son[maxn];
int fa[maxn]; //如果该节点有父节点,则fa[i]=1;否则为0,表示根节点
int tmp[maxn]; //dfs时的前驱
int pre[maxn]; //最大长度序列的前驱,也可以设置后驱,这样会方便点。
int ans[]; //输出的结果
int maxlen=; //序列的最大长度
int rear; //最长序列的尾节点 struct Word{
char str1[],str2[]; //str1为字符串,str2为对字符串中的字符排好序后的字符串
int len;
bool operator<(const Word tmp)const{
if(len==tmp.len){
if(strcmp(str2,tmp.str2)<=)
return true;
else
return false;
}
else
return len<tmp.len;
}
}word[maxn];
//判断字符串i和字符串j是否满足条件
bool isOk(int i,int j){
int l1=word[i].len;
int l2=word[j].len;
int idx=;
while(idx<l1&&word[i].str2[idx]==word[j].str2[idx])
idx++;
while(++idx<l2)
if(word[i].str2[idx-]!=word[j].str2[idx])
return false;
return true;
}
//深搜,确定以u为根节点到叶子节点的长度
void dfs(int u,int l){
if(son[u].empty()){
if(l>maxlen){
maxlen=l;
int k=u;
rear=u;
while(tmp[k]!=-){
pre[k]=tmp[k];
k=tmp[k];
}
pre[k]=-;
return;
}
}
int v;
for(int i=;i<son[u].size();i++){
v=son[u][i];
tmp[v]=u;
dfs(v,l+);
}
}
int main()
{
char s[];
while(scanf("%s",s)!=EOF){
strcpy(word[++n].str1,s);
strcpy(word[n].str2,s);
word[n].len=strlen(s);
sort(word[n].str2,word[n].str2+word[n].len);
}
sort(word+,word+n+);
memset(fa,,sizeof(fa));
for(int i=;i<=n;i++){
for(int j=i+;j<=n;j++){
if(word[i].len+==word[j].len){
if(isOk(i,j)){
son[i].push_back(j);
fa[j]=;
} }
//剪枝一下,从1766ms降到1266ms
else if(word[i].len+<word[j].len)
break;
}
}
memset(pre,-,sizeof(pre));
for(int i=;i<=n;i++){
//加上一个剪枝条件,不过速度没怎么变化。。。
if(!fa[i] && n-i+>maxlen){
memset(tmp,-,sizeof(tmp));
dfs(i,);
}
}
int p=rear;
int idx=;
ans[idx++]=p;
p=pre[p];
while(p!=-){
ans[idx++]=p;
p=pre[p];
}
for(int i=idx-;i>=;i--){
printf("%s\n",word[ans[i]].str1);
}
return ;
}
POJ 2004 Mix and Build (预处理+dfs)的更多相关文章
- Mix and Build(简单DP)
Mix and Build Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 3936 Accepted: 1203 Case Ti ...
- poj 1724 ROADS 很水的dfs
题意:给你N个城市和M条路和K块钱,每条路有话费,问你从1走到N的在K块钱内所能走的最短距离是多少 链接:http://poj.org/problem?id=1724 直接dfs搜一遍就是 代码: # ...
- POJ 2831 Can We Build This One:次小生成树【N^2预处理】
题目链接:http://poj.org/problem?id=2831 题意: 给你一个图,每条边有边权. 然后有q组询问(i,x),问你如果将第i条边的边权改为x,这条边是否有可能在新的最小生成树中 ...
- poj 2965 The Pilots Brothers' refrigerator (dfs)
The Pilots Brothers' refrigerator Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 17450 ...
- POJ 3321 树状数组(+dfs+重新建树)
Apple Tree Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 27092 Accepted: 8033 Descr ...
- POJ 3009 Curling 2.0 回溯,dfs 难度:0
http://poj.org/problem?id=3009 如果目前起点紧挨着终点,可以直接向终点滚(终点不算障碍) #include <cstdio> #include <cst ...
- POJ 1426 Find The Multiple --- BFS || DFS
POJ 1426 Find The Multiple 题意:给定一个整数n,求n的一个倍数,要求这个倍数只含0和1 参考博客:点我 解法一:普通的BFS(用G++能过但C++会超时) 从小到大搜索直至 ...
- poj 1564 Sum It Up (DFS+ 去重+排序)
http://poj.org/problem?id=1564 该题运用DFS但是要注意去重,不能输出重复的答案 两种去重方式代码中有标出 第一种if(a[i]!=a[i-1])意思是如果这个数a[i] ...
- poj 1979 Red and Black(dfs水题)
Description There is a rectangular room, covered with square tiles. Each tile is colored either red ...
随机推荐
- 小心C语言的定义与声明
小心C语言的定义与声明 转自360博客 注:为便于说明问题,文中提及的变量和函数都被简化. 一.起源 DBProxy在测试过程中,发现对其执行某步管理操作后,程序有时会崩溃,但不是每次都出现. 二.G ...
- STM32单片机实现中断后不继续向下执行而是返回到main函数
做公司的一个项目,实现一个功能就是 机器在进行一项功能时(这项工作时间挺长),想要取消这项工作,重新选择.想了半天没想出来,结果同事提醒了一句,可以在程序中加一个外部中断,在中断中软件复位程序.用到以 ...
- PAT乙级真题1003. 我要通过!(20)(解题)
“答案正确”是自动判题系统给出的最令人欢喜的回复.本题属于PAT的“答案正确”大派送 —— 只要读入的字符串满足下列条件,系统就输出“答案正确”,否则输出“答案错误”. 得到“答案正确”的条件是: 1 ...
- HDU1009
题意:有n个房子,每个房子里都有老鼠喜欢吃的咖啡豆J[i],但是每个房子都有猫看守,老鼠现在手上有M的猫粮.可以用猫粮换咖啡豆,每只猫都有猫粮的要求F[i].老鼠得到的咖啡豆是J[i]*a% ...
- scp 跨机远程拷贝
scp是secure copy的简写,用于在Linux下进行远程拷贝文件的命令,和它类似的命令有cp,不过cp只是在本机进行拷贝不能跨服务器. 命令格式: scp [参数] [原路径] [目标路径] ...
- MVC 中如何将带有标签的字符串转换为HTML 标签 显示出来?
出现问题的现象:
- Matlab实现单(双)极性(不)归零码
Matlab实现单(双)极性(不)归零码 内容大纲 Matlab实现单极性不归零波形(NRZ),0 1 幅值 Matlab实现单极性归零波形(RZ),0 1 幅值 Matlab实现双极性不归零波形,- ...
- Eclipse快捷键壁纸-0基础必备
- CentOS安装Git实现多人同步开发
描 述 要开发一个"cms系统",有2个人分别是:晓飞, 盈月.要求使用Git来进行版本控制. 项目信息 版本控制:Git 项目名称:cms 开发人员:xiaofei,yingyu ...
- C/C++常用头文件及函数汇总
转自: C/C++常用头文件及函数汇总 C/C++头文件一览 C #include <assert.h> //设定插入点#include <ctype.h> //字符处理#in ...